Abandoned Cart Lite for WooCommerce - Version 5.8.2

Version Description

(30.10.2020) = * Fix - Improved the code run in the action scheduler to include performance fixes. * Fix - Multiple instances of the woocommerce_ac_send_email action were observed in the Tools->Pending Actions. * Fix - Included sanitization of data & SQL queries for security purposes. * Fix - Optimized the plugin to use latest versions of JS and other libraries already present in WordPress.

Download this release

Release Info

Developer tychesoftwares
Plugin Icon 128x128 Abandoned Cart Lite for WooCommerce
Version 5.8.2
Comparing to
See all releases

Code changes from version 5.8.1 to 5.8.2

Files changed (33) hide show
  1. assets/css/admin/bootstrap.css +3 -3
  2. assets/css/admin/bootstrap.min.css +3 -3
  3. assets/js/admin/bootstrap.min.js +4 -4
  4. assets/js/jquery-ui.min.js +0 -13
  5. class-wcal-update.php +51 -3
  6. cron/wcal_send_email.php +252 -185
  7. includes/admin/class-wcal-personal-data-eraser.php +277 -0
  8. includes/admin/class-wcal-privacy-export.php +389 -0
  9. includes/admin/wcal_privacy_erase.php +0 -248
  10. includes/admin/wcal_privacy_export.php +0 -380
  11. includes/admin/wcap_add_cart_popup_modal.php +0 -71
  12. includes/admin/wcap_pro_settings.php +399 -726
  13. includes/admin/wcap_pro_settings_callbacks.php +220 -355
  14. includes/class-wcal-admin-notice.php +2 -3
  15. includes/classes/class-wcal-aes-counter.php +210 -167
  16. includes/classes/class-wcal-aes.php +471 -192
  17. includes/classes/class-wcal-dashboard-report.php +2 -2
  18. includes/classes/class-wcal-product-report-table.php +153 -147
  19. includes/classes/class-wcal-recover-orders-table.php +276 -265
  20. includes/classes/class-wcal-templates-table.php +177 -144
  21. includes/component/welcome-page/templates/welcome/welcome-page.php +0 -4
  22. includes/component/welcome-page/ts-welcome.php +2 -2
  23. includes/frontend/wcal_checkout_process.php +452 -443
  24. includes/frontend/wcal_frontend.php +9 -7
  25. includes/templates/template_1.php +133 -132
  26. includes/wcal-common.php +54 -19
  27. includes/wcal_all_component.php +181 -156
  28. includes/wcal_class-guest.php +140 -67
  29. includes/wcal_data_tracking_message.php +54 -52
  30. includes/wcal_process_base.php +26 -27
  31. readme.txt +7 -1
  32. uninstall.php +4 -1
  33. woocommerce-ac.php +1364 -1124
assets/css/admin/bootstrap.css CHANGED
@@ -1,7 +1,7 @@
1
  /*!
2
- * Bootstrap v4.1.0 (https://getbootstrap.com/)
3
- * Copyright 2011-2018 The Bootstrap Authors
4
- * Copyright 2011-2018 Twitter, Inc.
5
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6
  */
7
  :root {
1
  /*!
2
+ * Bootstrap v4.5.3 (https://getbootstrap.com/)
3
+ * Copyright 2011-2020 The Bootstrap Authors
4
+ * Copyright 2011-2020 Twitter, Inc.
5
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6
  */
7
  :root {
assets/css/admin/bootstrap.min.css CHANGED
@@ -1,6 +1,6 @@
1
  /*!
2
- * Bootstrap v4.1.0 (https://getbootstrap.com/)
3
- * Copyright 2011-2018 The Bootstrap Authors
4
- * Copyright 2011-2018 Twitter, Inc.
5
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6
  */dl,ol,pre,ul{margin-top:0;margin-bottom:1rem}address,dl,ol,pre,ul{margin-bottom:1rem}pre,textarea{overflow:auto}article,aside,dialog,figcaption,figure,footer,header,hgroup,legend,main,nav,section{display:block}dd,label,legend{margin-bottom:.5rem}address,legend{line-height:inherit}.badge,progress,sub,sup{vertical-align:baseline}label,output{display:inline-block}button,hr,input{overflow:visible}.btn-outline-danger,.btn-outline-dark,.btn-outline-info,.btn-outline-light,.btn-outline-primary,.btn-outline-success,.btn-outline-warning,.btn:not(:disabled):not(.disabled).active,.btn:not(:disabled):not(.disabled):active{background-image:none}.dropdown-menu,.form-control,.modal-content,.popover{background-clip:padding-box}.dropdown-menu,.nav,.navbar-nav{list-style:none}:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}@-ms-viewport{width:device-width}[tabindex="-1"]:focus{outline:0!important}abbr[data-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}.btn:not(:disabled):not(.disabled),.close:not(:disabled):not(.disabled),.navbar-toggler:not(:disabled):not(.disabled),.page-link:not(:disabled):not(.disabled),summary{cursor:pointer}address{font-style:normal}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-left:0}blockquote,figure{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0}sub{bottom:-.25em}sup{top:-.5em}code,kbd,pre,samp{font-size:1em}pre{-ms-overflow-style:scrollbar}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}button{border-radius:0}button:focus{outline:dotted 1px;outline:-webkit-focus-ring-color auto 5px}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[type=submit],[type=reset],button,html [type=button]{-webkit-appearance:button}[type=submit]::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{width:100%;max-width:100%;padding:0;font-size:1.5rem;color:inherit;white-space:normal}.blockquote,hr{margin-bottom:1rem}.badge,.btn,.dropdown-header,.dropdown-item,.input-group-text,.navbar-brand,.progress-bar{white-space:nowrap}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}.display-1,.display-2,.display-3,.display-4{font-weight:300;line-height:1.2}.text-monospace,code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}summary{display:list-item}template{display:none}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-4{font-size:3.5rem}hr{box-sizing:content-box;height:0;margin-top:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.img-fluid,.img-thumbnail{max-width:100%;height:auto}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014 \00A0"}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code,kbd{font-size:87.5%}a>code,pre code{color:inherit}code{color:#e83e8c;word-break:break-word}kbd{padding:.2rem .4rem;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}.container,.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto;width:100%}.btn,.btn-link,.dropdown-item{font-weight:400}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;max-width:100%;margin-bottom:1rem;background-color:transparent}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th,.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#212529;border-color:#32383e}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#212529}.table-dark td,.table-dark th,.table-dark thead th{border-color:#32383e}.table-dark.table-bordered,.table-responsive>.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.collapsing,.modal,.modal-open,.progress{overflow:hidden}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:not([size]):not([multiple]){height:calc(2.25rem + 2px)}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.custom-file-input.is-valid~.custom-file-label,.custom-select.is-valid,.form-control.is-valid,.was-validated .custom-file-input:valid~.custom-file-label,.was-validated .custom-select:valid,.was-validated .form-control:valid{border-color:#28a745}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm,.input-group-lg>.form-control-plaintext.form-control,.input-group-lg>.input-group-append>.form-control-plaintext.btn,.input-group-lg>.input-group-append>.form-control-plaintext.input-group-text,.input-group-lg>.input-group-prepend>.form-control-plaintext.btn,.input-group-lg>.input-group-prepend>.form-control-plaintext.input-group-text,.input-group-sm>.form-control-plaintext.form-control,.input-group-sm>.input-group-append>.form-control-plaintext.btn,.input-group-sm>.input-group-append>.form-control-plaintext.input-group-text,.input-group-sm>.input-group-prepend>.form-control-plaintext.btn,.input-group-sm>.input-group-prepend>.form-control-plaintext.input-group-text{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-sm>.input-group-append>select.btn:not([size]):not([multiple]),.input-group-sm>.input-group-append>select.input-group-text:not([size]):not([multiple]),.input-group-sm>.input-group-prepend>select.btn:not([size]):not([multiple]),.input-group-sm>.input-group-prepend>select.input-group-text:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),select.form-control-sm:not([size]):not([multiple]){height:calc(1.8125rem + 2px)}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-lg>.input-group-append>select.btn:not([size]):not([multiple]),.input-group-lg>.input-group-append>select.input-group-text:not([size]):not([multiple]),.input-group-lg>.input-group-prepend>select.btn:not([size]):not([multiple]),.input-group-lg>.input-group-prepend>select.input-group-text:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),select.form-control-lg:not([size]):not([multiple]){height:calc(2.875rem + 2px)}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.invalid-tooltip,.valid-tooltip{position:absolute;z-index:5;max-width:100%;padding:.5rem;line-height:1;border-radius:.2rem;top:100%}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{display:none;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(40,167,69,.8)}.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip,.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip,.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip,.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.form-check-input.is-valid~.form-check-label,.was-validated .custom-control-input:valid~.custom-control-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.custom-select.is-valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{background-color:#71dd8a}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(40,167,69,.25)}.custom-file-input.is-valid~.custom-file-label::before,.was-validated .custom-file-input:valid~.custom-file-label::before{border-color:inherit}.custom-file-input.is-invalid~.custom-file-label,.custom-select.is-invalid,.form-control.is-invalid,.was-validated .custom-file-input:invalid~.custom-file-label,.was-validated .custom-select:invalid,.was-validated .form-control:invalid{border-color:#dc3545}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{display:none;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.8)}.collapsing,.dropdown,.dropleft,.dropright,.dropup{position:relative}.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip,.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip,.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip,.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.form-check-input.is-invalid~.form-check-label,.was-validated .custom-control-input:invalid~.custom-control-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.custom-select.is-invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{background-color:#efa2a9}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(220,53,69,.25)}.custom-file-input.is-invalid~.custom-file-label::before,.was-validated .custom-file-input:invalid~.custom-file-label::before{border-color:inherit}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn-block,input[type=submit].btn-block,input[type=button].btn-block,input[type=reset].btn-block{width:100%}.btn{display:inline-block;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn:focus,.btn:hover{text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn-primary.focus,.btn-primary:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-success.focus,.btn-success:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-info.focus,.btn-info:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-warning.focus,.btn-warning:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-danger.focus,.btn-danger:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-light.focus,.btn-light:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-dark.focus,.btn-dark:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-outline-primary.focus,.btn-outline-primary:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary{color:#007bff;background-color:transparent;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-secondary.focus,.btn-outline-secondary:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary{color:#6c757d;background-color:transparent;background-image:none;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-success.focus,.btn-outline-success:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success{color:#28a745;background-color:transparent;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-info.focus,.btn-outline-info:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info{color:#17a2b8;background-color:transparent;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-warning.focus,.btn-outline-warning:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning{color:#ffc107;background-color:transparent;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-danger.focus,.btn-outline-danger:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger{color:#dc3545;background-color:transparent;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-light.focus,.btn-outline-light:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light{color:#f8f9fa;background-color:transparent;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-dark.focus,.btn-outline-dark:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark{color:#343a40;background-color:transparent;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-link,.btn-link:hover{background-color:transparent}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline;border-color:transparent}.btn-link{color:#007bff}.btn-link:hover{color:#0056b3}.btn-link.focus,.btn-link:focus{box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block}.btn-block+.btn-block{margin-top:.5rem}.dropdown-toggle::after,.dropup .dropdown-toggle::after{width:0;height:0;vertical-align:.255em;content:""}@media screen and (prefers-reduced-motion:reduce){.btn,.fade{transition:none}}.collapse:not(.show){display:none}.collapsing{height:0;transition:height .35s ease}@media screen and (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown-toggle::after{display:inline-block;margin-left:.255em;border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-right{right:0;left:auto}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropleft .dropdown-toggle::before,.dropright .dropdown-toggle::after{width:0;content:"";border-top:.3em solid transparent;border-bottom:.3em solid transparent;height:0}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;border-right:0;border-left:.3em solid;vertical-align:0}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;border-right:.3em solid;vertical-align:0}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropdown-menu[x-placement^=top],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn,.custom-control-label,.custom-file,.dropdown-header,.input-group-text,.nav{margin-bottom:0}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;color:#212529;text-align:inherit;background-color:transparent;border:0}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after,.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child),.input-group>.custom-file:not(:first-child) .custom-file-label,.input-group>.custom-file:not(:first-child) .custom-file-label::after,.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;font-size:.875rem;color:#6c757d}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-group>.btn:first-child,.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.input-group-append,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text,.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control{margin-left:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file:focus,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-prepend{margin-right:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=radio],.input-group-text input[type=checkbox]{margin-top:0}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-label::after,.custom-control-label::before{position:absolute;top:.25rem;display:block;width:1rem;height:1rem;content:"";left:0}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:active~.custom-control-label::before{color:#fff;background-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label::before{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#dee2e6}.custom-checkbox .custom-control-input:checked~.custom-control-label::before,.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{background-color:#007bff}.custom-control-label::after{background-repeat:no-repeat;background-position:center center;background-size:50% 50%}.custom-file-input:lang(en)~.custom-file-label::after,.custom-file-label::after{content:"Browse"}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before,.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::before{background-color:#007bff}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.5;color:#495057;vertical-align:middle;background:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center no-repeat #fff;background-size:8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select-lg,.custom-select-sm{padding-top:.375rem;padding-bottom:.375rem}.custom-file-input:focus~.custom-file-label::after,.custom-select:focus{border-color:#80bdff}.custom-select:focus{outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 5px rgba(128,189,255,.5)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:calc(1.8125rem + 2px);font-size:75%}.custom-select-lg{height:calc(2.875rem + 2px);font-size:125%}.custom-file,.custom-file-input,.custom-file-label{height:calc(2.25rem + 2px)}.custom-file{position:relative;display:inline-block;width:100%}.custom-file-input{position:relative;z-index:2;width:100%;margin:0;opacity:0}.custom-file-label,.custom-file-label::after{position:absolute;padding:.375rem .75rem;line-height:1.5;color:#495057;top:0;right:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-label{left:0;z-index:1;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{bottom:0;z-index:3;display:block;height:calc(calc(2.25rem + 2px) - 1px * 2);background-color:#e9ecef;border-left:1px solid #ced4da;border-radius:0 .25rem .25rem 0}.nav,.navbar{display:-ms-flexbox;-ms-flex-wrap:wrap}.custom-range{width:100%;padding-left:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-appearance:none;appearance:none}.custom-range::-webkit-slider-thumb:focus{outline:0;box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-appearance:none;appearance:none}.custom-range::-moz-range-thumb:focus{outline:0;box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;appearance:none}.custom-range::-ms-thumb:focus{outline:0;box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.nav{display:flex;flex-wrap:wrap;padding-left:0}.nav-link,.navbar{padding:.5rem 1rem}.nav-link{display:block}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar>.container,.navbar>.container-fluid{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit}.card,.navbar-nav{display:-ms-flexbox}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:center center no-repeat;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-footer,.card-header{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03)}.card-title{margin-bottom:.75rem}.card-header,.card-subtitle,.card-text:last-child{margin-bottom:0}.card-subtitle{margin-top:-.375rem}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header-pills,.card-header-tabs{margin-right:-.625rem;margin-left:-.625rem}.card-header{border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-bottom:-.75rem;border-bottom:0}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.alert,.btn .badge,.page-link{position:relative}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-ms-flexbox;display:flex;-ms-flex:1 0 0%;flex:1 0 0%;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:first-child .card-header,.card-group>.card:first-child .card-img-top{border-top-right-radius:0}.card-group>.card:first-child .card-footer,.card-group>.card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:last-child .card-header,.card-group>.card:last-child .card-img-top{border-top-left-radius:0}.card-group>.card:last-child .card-footer,.card-group>.card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group>.card:only-child{border-radius:.25rem}.card-group>.card:only-child .card-header,.card-group>.card:only-child .card-img-top{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-group>.card:only-child .card-footer,.card-group>.card:only-child .card-img-bottom{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-group>.card:not(:first-child):not(:last-child):not(:only-child),.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top{border-radius:0}.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.card-columns .card{margin-bottom:.75rem}.accordion .card:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion .card:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion .card:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion .card:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.breadcrumb,.pagination{border-radius:.25rem;list-style:none}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;background-color:#e9ecef}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0}.page-link,.popover-body,.popover-header{padding:.5rem .75rem}.page-link{display:block;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.badge,.close{font-weight:700;line-height:1}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;text-align:center;border-radius:.25rem}.badge:empty{display:none}.btn .badge{top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}.badge-primary[href]:focus,.badge-primary[href]:hover{color:#fff;text-decoration:none;background-color:#0062cc}.badge-secondary{color:#fff;background-color:#6c757d}.badge-secondary[href]:focus,.badge-secondary[href]:hover{color:#fff;text-decoration:none;background-color:#545b62}.badge-success{color:#fff;background-color:#28a745}.badge-success[href]:focus,.badge-success[href]:hover{color:#fff;text-decoration:none;background-color:#1e7e34}.badge-info{color:#fff;background-color:#17a2b8}.badge-info[href]:focus,.badge-info[href]:hover{color:#fff;text-decoration:none;background-color:#117a8b}.badge-warning{color:#212529;background-color:#ffc107}.badge-warning[href]:focus,.badge-warning[href]:hover{color:#212529;text-decoration:none;background-color:#d39e00}.badge-danger{color:#fff;background-color:#dc3545}.badge-danger[href]:focus,.badge-danger[href]:hover{color:#fff;text-decoration:none;background-color:#bd2130}.badge-light{color:#212529;background-color:#f8f9fa}.badge-light[href]:focus,.badge-light[href]:hover{color:#212529;text-decoration:none;background-color:#dae0e5}.badge-dark{color:#fff;background-color:#343a40}.badge-dark[href]:focus,.badge-dark[href]:hover{color:#fff;text-decoration:none;background-color:#1d2124}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;background-color:#007bff;transition:width .6s ease}@media screen and (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:focus,.list-group-item:hover{z-index:1;text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.popover,.tooltip{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-style:normal;font-weight:400;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;text-decoration:none}.modal-title,.popover,.tooltip{line-height:1.5}.popover,.text-hide,.tooltip{text-shadow:none}.close:focus,.close:hover{color:#000;text-decoration:none;opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;outline:0}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-25%);transform:translate(0,-25%)}@media screen and (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:translate(0,0);transform:translate(0,0)}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - (.5rem * 2))}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem;border-bottom:1px solid #e9ecef;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #e9ecef}.popover,.popover .arrow,.popover .arrow::after,.popover .arrow::before,.tooltip,.tooltip .arrow{position:absolute;display:block}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-centered{min-height:calc(100% - (1.75rem * 2))}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:800px}}.tooltip{z-index:1070;margin:0;text-align:left;text-align:start;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{top:0;left:0;z-index:1060;max-width:276px;text-align:left;text-align:start;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top] .arrow,.bs-popover-top .arrow{bottom:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=top] .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::after,.bs-popover-top .arrow::before{border-width:.5rem .5rem 0}.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::before{bottom:0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top] .arrow::after,.bs-popover-top .arrow::after{bottom:1px;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right] .arrow,.bs-popover-right .arrow{left:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right] .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::after,.bs-popover-right .arrow::before{border-width:.5rem .5rem .5rem 0}.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::before{left:0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right] .arrow::after,.bs-popover-right .arrow::after{left:1px;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom] .arrow,.bs-popover-bottom .arrow{top:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=bottom] .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::after,.bs-popover-bottom .arrow::before{border-width:0 .5rem .5rem}.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::before{top:0;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom] .arrow::after,.bs-popover-bottom .arrow::after{top:1px;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.carousel,.carousel-inner,.carousel-item{position:relative}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left] .arrow,.bs-popover-left .arrow{right:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left] .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::after,.bs-popover-left .arrow::before{border-width:.5rem 0 .5rem .5rem}.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::before{right:0;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left] .arrow::after,.bs-popover-left .arrow::after{right:1px;border-left-color:#fff}.popover-header{margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{color:#212529}.carousel-inner{width:100%;overflow:hidden}.carousel-item{display:none;-ms-flex-align:center;align-items:center;width:100%;transition:-webkit-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}@media screen and (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);transform:translateX(0)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translateX(100%);transform:translateX(100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translateX(-100%);transform:translateX(-100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-fade .carousel-item{opacity:0;transition-duration:.6s;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev,.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active{-webkit-transform:translateX(0);transform:translateX(0)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev,.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:center center no-repeat;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;background-color:rgba(255,255,255,.5)}.carousel-indicators li::after,.carousel-indicators li::before{left:0;display:inline-block;height:10px;position:absolute;content:"";width:100%}.carousel-indicators li::before{top:-10px}.carousel-indicators li::after{bottom:-10px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-left,.rounded-top{border-top-left-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-circle{border-radius:50%!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-bottom,.fixed-top{position:fixed;right:0;left:0;z-index:1030}.fixed-top{top:0}.fixed-bottom{bottom:0}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0062cc!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#545b62!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#1e7e34!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#117a8b!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#d39e00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#bd2130!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#dae0e5!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#1d2124!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{blockquote,img,pre,tr{page-break-inside:avoid}*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd}thead{display:table-header-group}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}}
1
  /*!
2
+ * Bootstrap v4.5.3 (https://getbootstrap.com/)
3
+ * Copyright 2011-2020 The Bootstrap Authors
4
+ * Copyright 2011-2020 Twitter, Inc.
5
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6
  */dl,ol,pre,ul{margin-top:0;margin-bottom:1rem}address,dl,ol,pre,ul{margin-bottom:1rem}pre,textarea{overflow:auto}article,aside,dialog,figcaption,figure,footer,header,hgroup,legend,main,nav,section{display:block}dd,label,legend{margin-bottom:.5rem}address,legend{line-height:inherit}.badge,progress,sub,sup{vertical-align:baseline}label,output{display:inline-block}button,hr,input{overflow:visible}.btn-outline-danger,.btn-outline-dark,.btn-outline-info,.btn-outline-light,.btn-outline-primary,.btn-outline-success,.btn-outline-warning,.btn:not(:disabled):not(.disabled).active,.btn:not(:disabled):not(.disabled):active{background-image:none}.dropdown-menu,.form-control,.modal-content,.popover{background-clip:padding-box}.dropdown-menu,.nav,.navbar-nav{list-style:none}:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}@-ms-viewport{width:device-width}[tabindex="-1"]:focus{outline:0!important}abbr[data-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}.btn:not(:disabled):not(.disabled),.close:not(:disabled):not(.disabled),.navbar-toggler:not(:disabled):not(.disabled),.page-link:not(:disabled):not(.disabled),summary{cursor:pointer}address{font-style:normal}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-left:0}blockquote,figure{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0}sub{bottom:-.25em}sup{top:-.5em}code,kbd,pre,samp{font-size:1em}pre{-ms-overflow-style:scrollbar}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}button{border-radius:0}button:focus{outline:dotted 1px;outline:-webkit-focus-ring-color auto 5px}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[type=submit],[type=reset],button,html [type=button]{-webkit-appearance:button}[type=submit]::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{width:100%;max-width:100%;padding:0;font-size:1.5rem;color:inherit;white-space:normal}.blockquote,hr{margin-bottom:1rem}.badge,.btn,.dropdown-header,.dropdown-item,.input-group-text,.navbar-brand,.progress-bar{white-space:nowrap}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}.display-1,.display-2,.display-3,.display-4{font-weight:300;line-height:1.2}.text-monospace,code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}summary{display:list-item}template{display:none}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-4{font-size:3.5rem}hr{box-sizing:content-box;height:0;margin-top:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.img-fluid,.img-thumbnail{max-width:100%;height:auto}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014 \00A0"}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code,kbd{font-size:87.5%}a>code,pre code{color:inherit}code{color:#e83e8c;word-break:break-word}kbd{padding:.2rem .4rem;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}.container,.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto;width:100%}.btn,.btn-link,.dropdown-item{font-weight:400}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;max-width:100%;margin-bottom:1rem;background-color:transparent}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th,.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#212529;border-color:#32383e}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#212529}.table-dark td,.table-dark th,.table-dark thead th{border-color:#32383e}.table-dark.table-bordered,.table-responsive>.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.collapsing,.modal,.modal-open,.progress{overflow:hidden}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:not([size]):not([multiple]){height:calc(2.25rem + 2px)}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.custom-file-input.is-valid~.custom-file-label,.custom-select.is-valid,.form-control.is-valid,.was-validated .custom-file-input:valid~.custom-file-label,.was-validated .custom-select:valid,.was-validated .form-control:valid{border-color:#28a745}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm,.input-group-lg>.form-control-plaintext.form-control,.input-group-lg>.input-group-append>.form-control-plaintext.btn,.input-group-lg>.input-group-append>.form-control-plaintext.input-group-text,.input-group-lg>.input-group-prepend>.form-control-plaintext.btn,.input-group-lg>.input-group-prepend>.form-control-plaintext.input-group-text,.input-group-sm>.form-control-plaintext.form-control,.input-group-sm>.input-group-append>.form-control-plaintext.btn,.input-group-sm>.input-group-append>.form-control-plaintext.input-group-text,.input-group-sm>.input-group-prepend>.form-control-plaintext.btn,.input-group-sm>.input-group-prepend>.form-control-plaintext.input-group-text{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-sm>.input-group-append>select.btn:not([size]):not([multiple]),.input-group-sm>.input-group-append>select.input-group-text:not([size]):not([multiple]),.input-group-sm>.input-group-prepend>select.btn:not([size]):not([multiple]),.input-group-sm>.input-group-prepend>select.input-group-text:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),select.form-control-sm:not([size]):not([multiple]){height:calc(1.8125rem + 2px)}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-lg>.input-group-append>select.btn:not([size]):not([multiple]),.input-group-lg>.input-group-append>select.input-group-text:not([size]):not([multiple]),.input-group-lg>.input-group-prepend>select.btn:not([size]):not([multiple]),.input-group-lg>.input-group-prepend>select.input-group-text:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),select.form-control-lg:not([size]):not([multiple]){height:calc(2.875rem + 2px)}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.invalid-tooltip,.valid-tooltip{position:absolute;z-index:5;max-width:100%;padding:.5rem;line-height:1;border-radius:.2rem;top:100%}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{display:none;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(40,167,69,.8)}.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip,.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip,.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip,.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.form-check-input.is-valid~.form-check-label,.was-validated .custom-control-input:valid~.custom-control-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.custom-select.is-valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{background-color:#71dd8a}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(40,167,69,.25)}.custom-file-input.is-valid~.custom-file-label::before,.was-validated .custom-file-input:valid~.custom-file-label::before{border-color:inherit}.custom-file-input.is-invalid~.custom-file-label,.custom-select.is-invalid,.form-control.is-invalid,.was-validated .custom-file-input:invalid~.custom-file-label,.was-validated .custom-select:invalid,.was-validated .form-control:invalid{border-color:#dc3545}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{display:none;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.8)}.collapsing,.dropdown,.dropleft,.dropright,.dropup{position:relative}.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip,.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip,.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip,.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.form-check-input.is-invalid~.form-check-label,.was-validated .custom-control-input:invalid~.custom-control-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.custom-select.is-invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{background-color:#efa2a9}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(220,53,69,.25)}.custom-file-input.is-invalid~.custom-file-label::before,.was-validated .custom-file-input:invalid~.custom-file-label::before{border-color:inherit}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn-block,input[type=submit].btn-block,input[type=button].btn-block,input[type=reset].btn-block{width:100%}.btn{display:inline-block;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn:focus,.btn:hover{text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn-primary.focus,.btn-primary:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-success.focus,.btn-success:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-info.focus,.btn-info:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-warning.focus,.btn-warning:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-danger.focus,.btn-danger:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-light.focus,.btn-light:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-dark.focus,.btn-dark:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-outline-primary.focus,.btn-outline-primary:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary{color:#007bff;background-color:transparent;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-secondary.focus,.btn-outline-secondary:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary{color:#6c757d;background-color:transparent;background-image:none;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-success.focus,.btn-outline-success:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success{color:#28a745;background-color:transparent;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-info.focus,.btn-outline-info:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info{color:#17a2b8;background-color:transparent;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-warning.focus,.btn-outline-warning:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning{color:#ffc107;background-color:transparent;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-danger.focus,.btn-outline-danger:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger{color:#dc3545;background-color:transparent;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-light.focus,.btn-outline-light:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light{color:#f8f9fa;background-color:transparent;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-dark.focus,.btn-outline-dark:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark{color:#343a40;background-color:transparent;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-link,.btn-link:hover{background-color:transparent}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline;border-color:transparent}.btn-link{color:#007bff}.btn-link:hover{color:#0056b3}.btn-link.focus,.btn-link:focus{box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block}.btn-block+.btn-block{margin-top:.5rem}.dropdown-toggle::after,.dropup .dropdown-toggle::after{width:0;height:0;vertical-align:.255em;content:""}@media screen and (prefers-reduced-motion:reduce){.btn,.fade{transition:none}}.collapse:not(.show){display:none}.collapsing{height:0;transition:height .35s ease}@media screen and (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown-toggle::after{display:inline-block;margin-left:.255em;border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-right{right:0;left:auto}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropleft .dropdown-toggle::before,.dropright .dropdown-toggle::after{width:0;content:"";border-top:.3em solid transparent;border-bottom:.3em solid transparent;height:0}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;border-right:0;border-left:.3em solid;vertical-align:0}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;border-right:.3em solid;vertical-align:0}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropdown-menu[x-placement^=top],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn,.custom-control-label,.custom-file,.dropdown-header,.input-group-text,.nav{margin-bottom:0}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;color:#212529;text-align:inherit;background-color:transparent;border:0}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after,.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child),.input-group>.custom-file:not(:first-child) .custom-file-label,.input-group>.custom-file:not(:first-child) .custom-file-label::after,.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;font-size:.875rem;color:#6c757d}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-group>.btn:first-child,.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.input-group-append,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text,.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control{margin-left:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file:focus,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-prepend{margin-right:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=radio],.input-group-text input[type=checkbox]{margin-top:0}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-label::after,.custom-control-label::before{position:absolute;top:.25rem;display:block;width:1rem;height:1rem;content:"";left:0}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:active~.custom-control-label::before{color:#fff;background-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label::before{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#dee2e6}.custom-checkbox .custom-control-input:checked~.custom-control-label::before,.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{background-color:#007bff}.custom-control-label::after{background-repeat:no-repeat;background-position:center center;background-size:50% 50%}.custom-file-input:lang(en)~.custom-file-label::after,.custom-file-label::after{content:"Browse"}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before,.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::before{background-color:#007bff}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.5;color:#495057;vertical-align:middle;background:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center no-repeat #fff;background-size:8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select-lg,.custom-select-sm{padding-top:.375rem;padding-bottom:.375rem}.custom-file-input:focus~.custom-file-label::after,.custom-select:focus{border-color:#80bdff}.custom-select:focus{outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 5px rgba(128,189,255,.5)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:calc(1.8125rem + 2px);font-size:75%}.custom-select-lg{height:calc(2.875rem + 2px);font-size:125%}.custom-file,.custom-file-input,.custom-file-label{height:calc(2.25rem + 2px)}.custom-file{position:relative;display:inline-block;width:100%}.custom-file-input{position:relative;z-index:2;width:100%;margin:0;opacity:0}.custom-file-label,.custom-file-label::after{position:absolute;padding:.375rem .75rem;line-height:1.5;color:#495057;top:0;right:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-label{left:0;z-index:1;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{bottom:0;z-index:3;display:block;height:calc(calc(2.25rem + 2px) - 1px * 2);background-color:#e9ecef;border-left:1px solid #ced4da;border-radius:0 .25rem .25rem 0}.nav,.navbar{display:-ms-flexbox;-ms-flex-wrap:wrap}.custom-range{width:100%;padding-left:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-appearance:none;appearance:none}.custom-range::-webkit-slider-thumb:focus{outline:0;box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-appearance:none;appearance:none}.custom-range::-moz-range-thumb:focus{outline:0;box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;appearance:none}.custom-range::-ms-thumb:focus{outline:0;box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.nav{display:flex;flex-wrap:wrap;padding-left:0}.nav-link,.navbar{padding:.5rem 1rem}.nav-link{display:block}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar>.container,.navbar>.container-fluid{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit}.card,.navbar-nav{display:-ms-flexbox}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:center center no-repeat;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-footer,.card-header{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03)}.card-title{margin-bottom:.75rem}.card-header,.card-subtitle,.card-text:last-child{margin-bottom:0}.card-subtitle{margin-top:-.375rem}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header-pills,.card-header-tabs{margin-right:-.625rem;margin-left:-.625rem}.card-header{border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-bottom:-.75rem;border-bottom:0}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.alert,.btn .badge,.page-link{position:relative}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-ms-flexbox;display:flex;-ms-flex:1 0 0%;flex:1 0 0%;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:first-child .card-header,.card-group>.card:first-child .card-img-top{border-top-right-radius:0}.card-group>.card:first-child .card-footer,.card-group>.card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:last-child .card-header,.card-group>.card:last-child .card-img-top{border-top-left-radius:0}.card-group>.card:last-child .card-footer,.card-group>.card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group>.card:only-child{border-radius:.25rem}.card-group>.card:only-child .card-header,.card-group>.card:only-child .card-img-top{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-group>.card:only-child .card-footer,.card-group>.card:only-child .card-img-bottom{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-group>.card:not(:first-child):not(:last-child):not(:only-child),.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top{border-radius:0}.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.card-columns .card{margin-bottom:.75rem}.accordion .card:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion .card:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion .card:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion .card:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.breadcrumb,.pagination{border-radius:.25rem;list-style:none}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;background-color:#e9ecef}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0}.page-link,.popover-body,.popover-header{padding:.5rem .75rem}.page-link{display:block;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.badge,.close{font-weight:700;line-height:1}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;text-align:center;border-radius:.25rem}.badge:empty{display:none}.btn .badge{top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}.badge-primary[href]:focus,.badge-primary[href]:hover{color:#fff;text-decoration:none;background-color:#0062cc}.badge-secondary{color:#fff;background-color:#6c757d}.badge-secondary[href]:focus,.badge-secondary[href]:hover{color:#fff;text-decoration:none;background-color:#545b62}.badge-success{color:#fff;background-color:#28a745}.badge-success[href]:focus,.badge-success[href]:hover{color:#fff;text-decoration:none;background-color:#1e7e34}.badge-info{color:#fff;background-color:#17a2b8}.badge-info[href]:focus,.badge-info[href]:hover{color:#fff;text-decoration:none;background-color:#117a8b}.badge-warning{color:#212529;background-color:#ffc107}.badge-warning[href]:focus,.badge-warning[href]:hover{color:#212529;text-decoration:none;background-color:#d39e00}.badge-danger{color:#fff;background-color:#dc3545}.badge-danger[href]:focus,.badge-danger[href]:hover{color:#fff;text-decoration:none;background-color:#bd2130}.badge-light{color:#212529;background-color:#f8f9fa}.badge-light[href]:focus,.badge-light[href]:hover{color:#212529;text-decoration:none;background-color:#dae0e5}.badge-dark{color:#fff;background-color:#343a40}.badge-dark[href]:focus,.badge-dark[href]:hover{color:#fff;text-decoration:none;background-color:#1d2124}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;background-color:#007bff;transition:width .6s ease}@media screen and (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:focus,.list-group-item:hover{z-index:1;text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.popover,.tooltip{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-style:normal;font-weight:400;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;text-decoration:none}.modal-title,.popover,.tooltip{line-height:1.5}.popover,.text-hide,.tooltip{text-shadow:none}.close:focus,.close:hover{color:#000;text-decoration:none;opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;outline:0}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-25%);transform:translate(0,-25%)}@media screen and (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:translate(0,0);transform:translate(0,0)}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - (.5rem * 2))}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem;border-bottom:1px solid #e9ecef;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #e9ecef}.popover,.popover .arrow,.popover .arrow::after,.popover .arrow::before,.tooltip,.tooltip .arrow{position:absolute;display:block}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-centered{min-height:calc(100% - (1.75rem * 2))}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:800px}}.tooltip{z-index:1070;margin:0;text-align:left;text-align:start;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{top:0;left:0;z-index:1060;max-width:276px;text-align:left;text-align:start;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top] .arrow,.bs-popover-top .arrow{bottom:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=top] .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::after,.bs-popover-top .arrow::before{border-width:.5rem .5rem 0}.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::before{bottom:0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top] .arrow::after,.bs-popover-top .arrow::after{bottom:1px;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right] .arrow,.bs-popover-right .arrow{left:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right] .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::after,.bs-popover-right .arrow::before{border-width:.5rem .5rem .5rem 0}.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::before{left:0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right] .arrow::after,.bs-popover-right .arrow::after{left:1px;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom] .arrow,.bs-popover-bottom .arrow{top:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=bottom] .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::after,.bs-popover-bottom .arrow::before{border-width:0 .5rem .5rem}.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::before{top:0;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom] .arrow::after,.bs-popover-bottom .arrow::after{top:1px;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.carousel,.carousel-inner,.carousel-item{position:relative}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left] .arrow,.bs-popover-left .arrow{right:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left] .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::after,.bs-popover-left .arrow::before{border-width:.5rem 0 .5rem .5rem}.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::before{right:0;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left] .arrow::after,.bs-popover-left .arrow::after{right:1px;border-left-color:#fff}.popover-header{margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{color:#212529}.carousel-inner{width:100%;overflow:hidden}.carousel-item{display:none;-ms-flex-align:center;align-items:center;width:100%;transition:-webkit-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}@media screen and (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);transform:translateX(0)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translateX(100%);transform:translateX(100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translateX(-100%);transform:translateX(-100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-fade .carousel-item{opacity:0;transition-duration:.6s;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev,.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active{-webkit-transform:translateX(0);transform:translateX(0)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev,.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:center center no-repeat;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;background-color:rgba(255,255,255,.5)}.carousel-indicators li::after,.carousel-indicators li::before{left:0;display:inline-block;height:10px;position:absolute;content:"";width:100%}.carousel-indicators li::before{top:-10px}.carousel-indicators li::after{bottom:-10px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-left,.rounded-top{border-top-left-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-circle{border-radius:50%!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-bottom,.fixed-top{position:fixed;right:0;left:0;z-index:1030}.fixed-top{top:0}.fixed-bottom{bottom:0}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0062cc!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#545b62!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#1e7e34!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#117a8b!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#d39e00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#bd2130!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#dae0e5!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#1d2124!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{blockquote,img,pre,tr{page-break-inside:avoid}*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd}thead{display:table-header-group}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}.container,body{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}}
assets/js/admin/bootstrap.min.js CHANGED
@@ -1,7 +1,7 @@
1
  /*!
2
- * Bootstrap v4.1.0 (https://getbootstrap.com/)
3
- * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5
  */
6
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e(t.bootstrap={},t.jQuery,t.Popper)}(this,function(t,e,c){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function o(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function h(r){for(var t=1;t<arguments.length;t++){var s=null!=arguments[t]?arguments[t]:{},e=Object.keys(s);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(s).filter(function(t){return Object.getOwnPropertyDescriptor(s,t).enumerable}))),e.forEach(function(t){var e,n,i;e=r,i=s[n=t],n in e?Object.defineProperty(e,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[n]=i})}return r}e=e&&e.hasOwnProperty("default")?e.default:e,c=c&&c.hasOwnProperty("default")?c.default:c;var r,n,s,a,l,u,f,d,_,g,m,p,v,E,y,T,C,I,A,D,b,S,w,N,O,k,P,L,j,R,H,W,M,x,U,K,F,V,Q,B,Y,G,q,z,X,J,Z,$,tt,et,nt,it,rt,st,ot,at,lt,ht,ct,ut,ft,dt,_t,gt,mt,pt,vt,Et,yt,Tt,Ct,It,At,Dt,bt,St,wt,Nt,Ot,kt,Pt,Lt,jt,Rt,Ht,Wt,Mt,xt,Ut,Kt,Ft,Vt,Qt,Bt,Yt,Gt,qt,zt,Xt,Jt,Zt,$t,te,ee,ne,ie,re,se,oe,ae,le,he,ce,ue,fe,de,_e,ge,me,pe,ve,Ee,ye,Te,Ce,Ie,Ae,De,be,Se,we,Ne,Oe,ke,Pe,Le,je,Re,He,We,Me,xe,Ue,Ke,Fe,Ve,Qe,Be,Ye,Ge,qe,ze,Xe,Je,Ze,$e,tn,en,nn,rn,sn,on,an,ln,hn,cn,un,fn,dn,_n,gn,mn,pn,vn,En,yn,Tn,Cn=function(i){var e="transitionend";function t(t){var e=this,n=!1;return i(this).one(l.TRANSITION_END,function(){n=!0}),setTimeout(function(){n||l.triggerTransitionEnd(e)},t),this}var l={TRANSITION_END:"bsTransitionEnd",getUID:function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");e&&"#"!==e||(e=t.getAttribute("href")||"");try{return 0<i(document).find(e).length?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var e=i(t).css("transition-duration");return parseFloat(e)?(e=e.split(",")[0],1e3*parseFloat(e)):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){i(t).trigger(e)},supportsTransitionEnd:function(){return Boolean(e)},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var r=n[i],s=e[i],o=s&&l.isElement(s)?"element":(a=s,{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase());if(!new RegExp(r).test(o))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+o+'" but expected type "'+r+'".')}var a}};return i.fn.emulateTransitionEnd=t,i.event.special[l.TRANSITION_END]={bindType:e,delegateType:e,handle:function(t){if(i(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}},l}(e),In=(n="alert",a="."+(s="bs.alert"),l=(r=e).fn[n],u={CLOSE:"close"+a,CLOSED:"closed"+a,CLICK_DATA_API:"click"+a+".data-api"},f="alert",d="fade",_="show",g=function(){function i(t){this._element=t}var t=i.prototype;return t.close=function(t){t=t||this._element;var e=this._getRootElement(t);this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},t.dispose=function(){r.removeData(this._element,s),this._element=null},t._getRootElement=function(t){var e=Cn.getSelectorFromElement(t),n=!1;return e&&(n=r(e)[0]),n||(n=r(t).closest("."+f)[0]),n},t._triggerCloseEvent=function(t){var e=r.Event(u.CLOSE);return r(t).trigger(e),e},t._removeElement=function(e){var n=this;if(r(e).removeClass(_),r(e).hasClass(d)){var t=Cn.getTransitionDurationFromElement(e);r(e).one(Cn.TRANSITION_END,function(t){return n._destroyElement(e,t)}).emulateTransitionEnd(t)}else this._destroyElement(e)},t._destroyElement=function(t){r(t).detach().trigger(u.CLOSED).remove()},i._jQueryInterface=function(n){return this.each(function(){var t=r(this),e=t.data(s);e||(e=new i(this),t.data(s,e)),"close"===n&&e[n](this)})},i._handleDismiss=function(e){return function(t){t&&t.preventDefault(),e.close(this)}},o(i,null,[{key:"VERSION",get:function(){return"4.1.0"}}]),i}(),r(document).on(u.CLICK_DATA_API,'[data-dismiss="alert"]',g._handleDismiss(new g)),r.fn[n]=g._jQueryInterface,r.fn[n].Constructor=g,r.fn[n].noConflict=function(){return r.fn[n]=l,g._jQueryInterface},g),An=(p="button",E="."+(v="bs.button"),y=".data-api",T=(m=e).fn[p],C="active",I="btn",D='[data-toggle^="button"]',b='[data-toggle="buttons"]',S="input",w=".active",N=".btn",O={CLICK_DATA_API:"click"+E+y,FOCUS_BLUR_DATA_API:(A="focus")+E+y+" blur"+E+y},k=function(){function n(t){this._element=t}var t=n.prototype;return t.toggle=function(){var t=!0,e=!0,n=m(this._element).closest(b)[0];if(n){var i=m(this._element).find(S)[0];if(i){if("radio"===i.type)if(i.checked&&m(this._element).hasClass(C))t=!1;else{var r=m(n).find(w)[0];r&&m(r).removeClass(C)}if(t){if(i.hasAttribute("disabled")||n.hasAttribute("disabled")||i.classList.contains("disabled")||n.classList.contains("disabled"))return;i.checked=!m(this._element).hasClass(C),m(i).trigger("change")}i.focus(),e=!1}}e&&this._element.setAttribute("aria-pressed",!m(this._element).hasClass(C)),t&&m(this._element).toggleClass(C)},t.dispose=function(){m.removeData(this._element,v),this._element=null},n._jQueryInterface=function(e){return this.each(function(){var t=m(this).data(v);t||(t=new n(this),m(this).data(v,t)),"toggle"===e&&t[e]()})},o(n,null,[{key:"VERSION",get:function(){return"4.1.0"}}]),n}(),m(document).on(O.CLICK_DATA_API,D,function(t){t.preventDefault();var e=t.target;m(e).hasClass(I)||(e=m(e).closest(N)),k._jQueryInterface.call(m(e),"toggle")}).on(O.FOCUS_BLUR_DATA_API,D,function(t){var e=m(t.target).closest(N)[0];m(e).toggleClass(A,/^focus(in)?$/.test(t.type))}),m.fn[p]=k._jQueryInterface,m.fn[p].Constructor=k,m.fn[p].noConflict=function(){return m.fn[p]=T,k._jQueryInterface},k),Dn=(L="carousel",R="."+(j="bs.carousel"),H=".data-api",W=(P=e).fn[L],M={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0},x={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean"},U="next",K="prev",F="left",V="right",Q={SLIDE:"slide"+R,SLID:"slid"+R,KEYDOWN:"keydown"+R,MOUSEENTER:"mouseenter"+R,MOUSELEAVE:"mouseleave"+R,TOUCHEND:"touchend"+R,LOAD_DATA_API:"load"+R+H,CLICK_DATA_API:"click"+R+H},B="carousel",Y="active",G="slide",q="carousel-item-right",z="carousel-item-left",X="carousel-item-next",J="carousel-item-prev",Z={ACTIVE:".active",ACTIVE_ITEM:".active.carousel-item",ITEM:".carousel-item",NEXT_PREV:".carousel-item-next, .carousel-item-prev",INDICATORS:".carousel-indicators",DATA_SLIDE:"[data-slide], [data-slide-to]",DATA_RIDE:'[data-ride="carousel"]'},$=function(){function s(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this._config=this._getConfig(e),this._element=P(t)[0],this._indicatorsElement=P(this._element).find(Z.INDICATORS)[0],this._addEventListeners()}var t=s.prototype;return t.next=function(){this._isSliding||this._slide(U)},t.nextWhenVisible=function(){!document.hidden&&P(this._element).is(":visible")&&"hidden"!==P(this._element).css("visibility")&&this.next()},t.prev=function(){this._isSliding||this._slide(K)},t.pause=function(t){t||(this._isPaused=!0),P(this._element).find(Z.NEXT_PREV)[0]&&(Cn.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},t.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},t.to=function(t){var e=this;this._activeElement=P(this._element).find(Z.ACTIVE_ITEM)[0];var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)P(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=n<t?U:K;this._slide(i,this._items[t])}},t.dispose=function(){P(this._element).off(R),P.removeData(this._element,j),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},t._getConfig=function(t){return t=h({},M,t),Cn.typeCheckConfig(L,t,x),t},t._addEventListeners=function(){var e=this;this._config.keyboard&&P(this._element).on(Q.KEYDOWN,function(t){return e._keydown(t)}),"hover"===this._config.pause&&(P(this._element).on(Q.MOUSEENTER,function(t){return e.pause(t)}).on(Q.MOUSELEAVE,function(t){return e.cycle(t)}),"ontouchstart"in document.documentElement&&P(this._element).on(Q.TOUCHEND,function(){e.pause(),e.touchTimeout&&clearTimeout(e.touchTimeout),e.touchTimeout=setTimeout(function(t){return e.cycle(t)},500+e._config.interval)}))},t._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},t._getItemIndex=function(t){return this._items=P.makeArray(P(t).parent().find(Z.ITEM)),this._items.indexOf(t)},t._getItemByDirection=function(t,e){var n=t===U,i=t===K,r=this._getItemIndex(e),s=this._items.length-1;if((i&&0===r||n&&r===s)&&!this._config.wrap)return e;var o=(r+(t===K?-1:1))%this._items.length;return-1===o?this._items[this._items.length-1]:this._items[o]},t._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(P(this._element).find(Z.ACTIVE_ITEM)[0]),r=P.Event(Q.SLIDE,{relatedTarget:t,direction:e,from:i,to:n});return P(this._element).trigger(r),r},t._setActiveIndicatorElement=function(t){if(this._indicatorsElement){P(this._indicatorsElement).find(Z.ACTIVE).removeClass(Y);var e=this._indicatorsElement.children[this._getItemIndex(t)];e&&P(e).addClass(Y)}},t._slide=function(t,e){var n,i,r,s=this,o=P(this._element).find(Z.ACTIVE_ITEM)[0],a=this._getItemIndex(o),l=e||o&&this._getItemByDirection(t,o),h=this._getItemIndex(l),c=Boolean(this._interval);if(t===U?(n=z,i=X,r=F):(n=q,i=J,r=V),l&&P(l).hasClass(Y))this._isSliding=!1;else if(!this._triggerSlideEvent(l,r).isDefaultPrevented()&&o&&l){this._isSliding=!0,c&&this.pause(),this._setActiveIndicatorElement(l);var u=P.Event(Q.SLID,{relatedTarget:l,direction:r,from:a,to:h});if(P(this._element).hasClass(G)){P(l).addClass(i),Cn.reflow(l),P(o).addClass(n),P(l).addClass(n);var f=Cn.getTransitionDurationFromElement(o);P(o).one(Cn.TRANSITION_END,function(){P(l).removeClass(n+" "+i).addClass(Y),P(o).removeClass(Y+" "+i+" "+n),s._isSliding=!1,setTimeout(function(){return P(s._element).trigger(u)},0)}).emulateTransitionEnd(f)}else P(o).removeClass(Y),P(l).addClass(Y),this._isSliding=!1,P(this._element).trigger(u);c&&this.cycle()}},s._jQueryInterface=function(i){return this.each(function(){var t=P(this).data(j),e=h({},M,P(this).data());"object"==typeof i&&(e=h({},e,i));var n="string"==typeof i?i:e.slide;if(t||(t=new s(this,e),P(this).data(j,t)),"number"==typeof i)t.to(i);else if("string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}else e.interval&&(t.pause(),t.cycle())})},s._dataApiClickHandler=function(t){var e=Cn.getSelectorFromElement(this);if(e){var n=P(e)[0];if(n&&P(n).hasClass(B)){var i=h({},P(n).data(),P(this).data()),r=this.getAttribute("data-slide-to");r&&(i.interval=!1),s._jQueryInterface.call(P(n),i),r&&P(n).data(j).to(r),t.preventDefault()}}},o(s,null,[{key:"VERSION",get:function(){return"4.1.0"}},{key:"Default",get:function(){return M}}]),s}(),P(document).on(Q.CLICK_DATA_API,Z.DATA_SLIDE,$._dataApiClickHandler),P(window).on(Q.LOAD_DATA_API,function(){P(Z.DATA_RIDE).each(function(){var t=P(this);$._jQueryInterface.call(t,t.data())})}),P.fn[L]=$._jQueryInterface,P.fn[L].Constructor=$,P.fn[L].noConflict=function(){return P.fn[L]=W,$._jQueryInterface},$),bn=(et="collapse",it="."+(nt="bs.collapse"),rt=(tt=e).fn[et],st={toggle:!0,parent:""},ot={toggle:"boolean",parent:"(string|element)"},at={SHOW:"show"+it,SHOWN:"shown"+it,HIDE:"hide"+it,HIDDEN:"hidden"+it,CLICK_DATA_API:"click"+it+".data-api"},lt="show",ht="collapse",ct="collapsing",ut="collapsed",ft="width",dt="height",_t={ACTIVES:".show, .collapsing",DATA_TOGGLE:'[data-toggle="collapse"]'},gt=function(){function a(t,e){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(e),this._triggerArray=tt.makeArray(tt('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var n=tt(_t.DATA_TOGGLE),i=0;i<n.length;i++){var r=n[i],s=Cn.getSelectorFromElement(r);null!==s&&0<tt(s).filter(t).length&&(this._selector=s,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var t=a.prototype;return t.toggle=function(){tt(this._element).hasClass(lt)?this.hide():this.show()},t.show=function(){var t,e,n=this;if(!this._isTransitioning&&!tt(this._element).hasClass(lt)&&(this._parent&&0===(t=tt.makeArray(tt(this._parent).find(_t.ACTIVES).filter('[data-parent="'+this._config.parent+'"]'))).length&&(t=null),!(t&&(e=tt(t).not(this._selector).data(nt))&&e._isTransitioning))){var i=tt.Event(at.SHOW);if(tt(this._element).trigger(i),!i.isDefaultPrevented()){t&&(a._jQueryInterface.call(tt(t).not(this._selector),"hide"),e||tt(t).data(nt,null));var r=this._getDimension();tt(this._element).removeClass(ht).addClass(ct),(this._element.style[r]=0)<this._triggerArray.length&&tt(this._triggerArray).removeClass(ut).attr("aria-expanded",!0),this.setTransitioning(!0);var s="scroll"+(r[0].toUpperCase()+r.slice(1)),o=Cn.getTransitionDurationFromElement(this._element);tt(this._element).one(Cn.TRANSITION_END,function(){tt(n._element).removeClass(ct).addClass(ht).addClass(lt),n._element.style[r]="",n.setTransitioning(!1),tt(n._element).trigger(at.SHOWN)}).emulateTransitionEnd(o),this._element.style[r]=this._element[s]+"px"}}},t.hide=function(){var t=this;if(!this._isTransitioning&&tt(this._element).hasClass(lt)){var e=tt.Event(at.HIDE);if(tt(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();if(this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",Cn.reflow(this._element),tt(this._element).addClass(ct).removeClass(ht).removeClass(lt),0<this._triggerArray.length)for(var i=0;i<this._triggerArray.length;i++){var r=this._triggerArray[i],s=Cn.getSelectorFromElement(r);if(null!==s)tt(s).hasClass(lt)||tt(r).addClass(ut).attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[n]="";var o=Cn.getTransitionDurationFromElement(this._element);tt(this._element).one(Cn.TRANSITION_END,function(){t.setTransitioning(!1),tt(t._element).removeClass(ct).addClass(ht).trigger(at.HIDDEN)}).emulateTransitionEnd(o)}}},t.setTransitioning=function(t){this._isTransitioning=t},t.dispose=function(){tt.removeData(this._element,nt),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},t._getConfig=function(t){return(t=h({},st,t)).toggle=Boolean(t.toggle),Cn.typeCheckConfig(et,t,ot),t},t._getDimension=function(){return tt(this._element).hasClass(ft)?ft:dt},t._getParent=function(){var n=this,t=null;Cn.isElement(this._config.parent)?(t=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(t=this._config.parent[0])):t=tt(this._config.parent)[0];var e='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]';return tt(t).find(e).each(function(t,e){n._addAriaAndCollapsedClass(a._getTargetFromElement(e),[e])}),t},t._addAriaAndCollapsedClass=function(t,e){if(t){var n=tt(t).hasClass(lt);0<e.length&&tt(e).toggleClass(ut,!n).attr("aria-expanded",n)}},a._getTargetFromElement=function(t){var e=Cn.getSelectorFromElement(t);return e?tt(e)[0]:null},a._jQueryInterface=function(i){return this.each(function(){var t=tt(this),e=t.data(nt),n=h({},st,t.data(),"object"==typeof i&&i);if(!e&&n.toggle&&/show|hide/.test(i)&&(n.toggle=!1),e||(e=new a(this,n),t.data(nt,e)),"string"==typeof i){if("undefined"==typeof e[i])throw new TypeError('No method named "'+i+'"');e[i]()}})},o(a,null,[{key:"VERSION",get:function(){return"4.1.0"}},{key:"Default",get:function(){return st}}]),a}(),tt(document).on(at.CLICK_DATA_API,_t.DATA_TOGGLE,function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=tt(this),e=Cn.getSelectorFromElement(this);tt(e).each(function(){var t=tt(this),e=t.data(nt)?"toggle":n.data();gt._jQueryInterface.call(t,e)})}),tt.fn[et]=gt._jQueryInterface,tt.fn[et].Constructor=gt,tt.fn[et].noConflict=function(){return tt.fn[et]=rt,gt._jQueryInterface},gt),Sn=(pt="dropdown",Et="."+(vt="bs.dropdown"),yt=".data-api",Tt=(mt=e).fn[pt],Ct=new RegExp("38|40|27"),It={HIDE:"hide"+Et,HIDDEN:"hidden"+Et,SHOW:"show"+Et,SHOWN:"shown"+Et,CLICK:"click"+Et,CLICK_DATA_API:"click"+Et+yt,KEYDOWN_DATA_API:"keydown"+Et+yt,KEYUP_DATA_API:"keyup"+Et+yt},At="disabled",Dt="show",bt="dropup",St="dropright",wt="dropleft",Nt="dropdown-menu-right",Ot="position-static",kt='[data-toggle="dropdown"]',Pt=".dropdown form",Lt=".dropdown-menu",jt=".navbar-nav",Rt=".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",Ht="top-start",Wt="top-end",Mt="bottom-start",xt="bottom-end",Ut="right-start",Kt="left-start",Ft={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic"},Vt={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string"},Qt=function(){function l(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var t=l.prototype;return t.toggle=function(){if(!this._element.disabled&&!mt(this._element).hasClass(At)){var t=l._getParentFromElement(this._element),e=mt(this._menu).hasClass(Dt);if(l._clearMenus(),!e){var n={relatedTarget:this._element},i=mt.Event(It.SHOW,n);if(mt(t).trigger(i),!i.isDefaultPrevented()){if(!this._inNavbar){if("undefined"==typeof c)throw new TypeError("Bootstrap dropdown require Popper.js (https://popper.js.org)");var r=this._element;"parent"===this._config.reference?r=t:Cn.isElement(this._config.reference)&&(r=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(r=this._config.reference[0])),"scrollParent"!==this._config.boundary&&mt(t).addClass(Ot),this._popper=new c(r,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===mt(t).closest(jt).length&&mt(document.body).children().on("mouseover",null,mt.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),mt(this._menu).toggleClass(Dt),mt(t).toggleClass(Dt).trigger(mt.Event(It.SHOWN,n))}}}},t.dispose=function(){mt.removeData(this._element,vt),mt(this._element).off(Et),this._element=null,(this._menu=null)!==this._popper&&(this._popper.destroy(),this._popper=null)},t.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},t._addEventListeners=function(){var e=this;mt(this._element).on(It.CLICK,function(t){t.preventDefault(),t.stopPropagation(),e.toggle()})},t._getConfig=function(t){return t=h({},this.constructor.Default,mt(this._element).data(),t),Cn.typeCheckConfig(pt,t,this.constructor.DefaultType),t},t._getMenuElement=function(){if(!this._menu){var t=l._getParentFromElement(this._element);this._menu=mt(t).find(Lt)[0]}return this._menu},t._getPlacement=function(){var t=mt(this._element).parent(),e=Mt;return t.hasClass(bt)?(e=Ht,mt(this._menu).hasClass(Nt)&&(e=Wt)):t.hasClass(St)?e=Ut:t.hasClass(wt)?e=Kt:mt(this._menu).hasClass(Nt)&&(e=xt),e},t._detectNavbar=function(){return 0<mt(this._element).closest(".navbar").length},t._getPopperConfig=function(){var e=this,t={};"function"==typeof this._config.offset?t.fn=function(t){return t.offsets=h({},t.offsets,e._config.offset(t.offsets)||{}),t}:t.offset=this._config.offset;var n={placement:this._getPlacement(),modifiers:{offset:t,flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(n.modifiers.applyStyle={enabled:!1}),n},l._jQueryInterface=function(e){return this.each(function(){var t=mt(this).data(vt);if(t||(t=new l(this,"object"==typeof e?e:null),mt(this).data(vt,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},l._clearMenus=function(t){if(!t||3!==t.which&&("keyup"!==t.type||9===t.which))for(var e=mt.makeArray(mt(kt)),n=0;n<e.length;n++){var i=l._getParentFromElement(e[n]),r=mt(e[n]).data(vt),s={relatedTarget:e[n]};if(r){var o=r._menu;if(mt(i).hasClass(Dt)&&!(t&&("click"===t.type&&/input|textarea/i.test(t.target.tagName)||"keyup"===t.type&&9===t.which)&&mt.contains(i,t.target))){var a=mt.Event(It.HIDE,s);mt(i).trigger(a),a.isDefaultPrevented()||("ontouchstart"in document.documentElement&&mt(document.body).children().off("mouseover",null,mt.noop),e[n].setAttribute("aria-expanded","false"),mt(o).removeClass(Dt),mt(i).removeClass(Dt).trigger(mt.Event(It.HIDDEN,s)))}}}},l._getParentFromElement=function(t){var e,n=Cn.getSelectorFromElement(t);return n&&(e=mt(n)[0]),e||t.parentNode},l._dataApiKeydownHandler=function(t){if((/input|textarea/i.test(t.target.tagName)?!(32===t.which||27!==t.which&&(40!==t.which&&38!==t.which||mt(t.target).closest(Lt).length)):Ct.test(t.which))&&(t.preventDefault(),t.stopPropagation(),!this.disabled&&!mt(this).hasClass(At))){var e=l._getParentFromElement(this),n=mt(e).hasClass(Dt);if((n||27===t.which&&32===t.which)&&(!n||27!==t.which&&32!==t.which)){var i=mt(e).find(Rt).get();if(0!==i.length){var r=i.indexOf(t.target);38===t.which&&0<r&&r--,40===t.which&&r<i.length-1&&r++,r<0&&(r=0),i[r].focus()}}else{if(27===t.which){var s=mt(e).find(kt)[0];mt(s).trigger("focus")}mt(this).trigger("click")}}},o(l,null,[{key:"VERSION",get:function(){return"4.1.0"}},{key:"Default",get:function(){return Ft}},{key:"DefaultType",get:function(){return Vt}}]),l}(),mt(document).on(It.KEYDOWN_DATA_API,kt,Qt._dataApiKeydownHandler).on(It.KEYDOWN_DATA_API,Lt,Qt._dataApiKeydownHandler).on(It.CLICK_DATA_API+" "+It.KEYUP_DATA_API,Qt._clearMenus).on(It.CLICK_DATA_API,kt,function(t){t.preventDefault(),t.stopPropagation(),Qt._jQueryInterface.call(mt(this),"toggle")}).on(It.CLICK_DATA_API,Pt,function(t){t.stopPropagation()}),mt.fn[pt]=Qt._jQueryInterface,mt.fn[pt].Constructor=Qt,mt.fn[pt].noConflict=function(){return mt.fn[pt]=Tt,Qt._jQueryInterface},Qt),wn=(Yt="modal",qt="."+(Gt="bs.modal"),zt=(Bt=e).fn[Yt],Xt={backdrop:!0,keyboard:!0,focus:!0,show:!0},Jt={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},Zt={HIDE:"hide"+qt,HIDDEN:"hidden"+qt,SHOW:"show"+qt,SHOWN:"shown"+qt,FOCUSIN:"focusin"+qt,RESIZE:"resize"+qt,CLICK_DISMISS:"click.dismiss"+qt,KEYDOWN_DISMISS:"keydown.dismiss"+qt,MOUSEUP_DISMISS:"mouseup.dismiss"+qt,MOUSEDOWN_DISMISS:"mousedown.dismiss"+qt,CLICK_DATA_API:"click"+qt+".data-api"},$t="modal-scrollbar-measure",te="modal-backdrop",ee="modal-open",ne="fade",ie="show",re={DIALOG:".modal-dialog",DATA_TOGGLE:'[data-toggle="modal"]',DATA_DISMISS:'[data-dismiss="modal"]',FIXED_CONTENT:".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",STICKY_CONTENT:".sticky-top",NAVBAR_TOGGLER:".navbar-toggler"},se=function(){function r(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=Bt(t).find(re.DIALOG)[0],this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._scrollbarWidth=0}var t=r.prototype;return t.toggle=function(t){return this._isShown?this.hide():this.show(t)},t.show=function(t){var e=this;if(!this._isTransitioning&&!this._isShown){Bt(this._element).hasClass(ne)&&(this._isTransitioning=!0);var n=Bt.Event(Zt.SHOW,{relatedTarget:t});Bt(this._element).trigger(n),this._isShown||n.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),Bt(document.body).addClass(ee),this._setEscapeEvent(),this._setResizeEvent(),Bt(this._element).on(Zt.CLICK_DISMISS,re.DATA_DISMISS,function(t){return e.hide(t)}),Bt(this._dialog).on(Zt.MOUSEDOWN_DISMISS,function(){Bt(e._element).one(Zt.MOUSEUP_DISMISS,function(t){Bt(t.target).is(e._element)&&(e._ignoreBackdropClick=!0)})}),this._showBackdrop(function(){return e._showElement(t)}))}},t.hide=function(t){var e=this;if(t&&t.preventDefault(),!this._isTransitioning&&this._isShown){var n=Bt.Event(Zt.HIDE);if(Bt(this._element).trigger(n),this._isShown&&!n.isDefaultPrevented()){this._isShown=!1;var i=Bt(this._element).hasClass(ne);if(i&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),Bt(document).off(Zt.FOCUSIN),Bt(this._element).removeClass(ie),Bt(this._element).off(Zt.CLICK_DISMISS),Bt(this._dialog).off(Zt.MOUSEDOWN_DISMISS),i){var r=Cn.getTransitionDurationFromElement(this._element);Bt(this._element).one(Cn.TRANSITION_END,function(t){return e._hideModal(t)}).emulateTransitionEnd(r)}else this._hideModal()}}},t.dispose=function(){Bt.removeData(this._element,Gt),Bt(window,document,this._element,this._backdrop).off(qt),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._scrollbarWidth=null},t.handleUpdate=function(){this._adjustDialog()},t._getConfig=function(t){return t=h({},Xt,t),Cn.typeCheckConfig(Yt,t,Jt),t},t._showElement=function(t){var e=this,n=Bt(this._element).hasClass(ne);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.scrollTop=0,n&&Cn.reflow(this._element),Bt(this._element).addClass(ie),this._config.focus&&this._enforceFocus();var i=Bt.Event(Zt.SHOWN,{relatedTarget:t}),r=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,Bt(e._element).trigger(i)};if(n){var s=Cn.getTransitionDurationFromElement(this._element);Bt(this._dialog).one(Cn.TRANSITION_END,r).emulateTransitionEnd(s)}else r()},t._enforceFocus=function(){var e=this;Bt(document).off(Zt.FOCUSIN).on(Zt.FOCUSIN,function(t){document!==t.target&&e._element!==t.target&&0===Bt(e._element).has(t.target).length&&e._element.focus()})},t._setEscapeEvent=function(){var e=this;this._isShown&&this._config.keyboard?Bt(this._element).on(Zt.KEYDOWN_DISMISS,function(t){27===t.which&&(t.preventDefault(),e.hide())}):this._isShown||Bt(this._element).off(Zt.KEYDOWN_DISMISS)},t._setResizeEvent=function(){var e=this;this._isShown?Bt(window).on(Zt.RESIZE,function(t){return e.handleUpdate(t)}):Bt(window).off(Zt.RESIZE)},t._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._isTransitioning=!1,this._showBackdrop(function(){Bt(document.body).removeClass(ee),t._resetAdjustments(),t._resetScrollbar(),Bt(t._element).trigger(Zt.HIDDEN)})},t._removeBackdrop=function(){this._backdrop&&(Bt(this._backdrop).remove(),this._backdrop=null)},t._showBackdrop=function(t){var e=this,n=Bt(this._element).hasClass(ne)?ne:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className=te,n&&Bt(this._backdrop).addClass(n),Bt(this._backdrop).appendTo(document.body),Bt(this._element).on(Zt.CLICK_DISMISS,function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._element.focus():e.hide())}),n&&Cn.reflow(this._backdrop),Bt(this._backdrop).addClass(ie),!t)return;if(!n)return void t();var i=Cn.getTransitionDurationFromElement(this._backdrop);Bt(this._backdrop).one(Cn.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){Bt(this._backdrop).removeClass(ie);var r=function(){e._removeBackdrop(),t&&t()};if(Bt(this._element).hasClass(ne)){var s=Cn.getTransitionDurationFromElement(this._backdrop);Bt(this._backdrop).one(Cn.TRANSITION_END,r).emulateTransitionEnd(s)}else r()}else t&&t()},t._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},t._setScrollbar=function(){var r=this;if(this._isBodyOverflowing){Bt(re.FIXED_CONTENT).each(function(t,e){var n=Bt(e)[0].style.paddingRight,i=Bt(e).css("padding-right");Bt(e).data("padding-right",n).css("padding-right",parseFloat(i)+r._scrollbarWidth+"px")}),Bt(re.STICKY_CONTENT).each(function(t,e){var n=Bt(e)[0].style.marginRight,i=Bt(e).css("margin-right");Bt(e).data("margin-right",n).css("margin-right",parseFloat(i)-r._scrollbarWidth+"px")}),Bt(re.NAVBAR_TOGGLER).each(function(t,e){var n=Bt(e)[0].style.marginRight,i=Bt(e).css("margin-right");Bt(e).data("margin-right",n).css("margin-right",parseFloat(i)+r._scrollbarWidth+"px")});var t=document.body.style.paddingRight,e=Bt(document.body).css("padding-right");Bt(document.body).data("padding-right",t).css("padding-right",parseFloat(e)+this._scrollbarWidth+"px")}},t._resetScrollbar=function(){Bt(re.FIXED_CONTENT).each(function(t,e){var n=Bt(e).data("padding-right");"undefined"!=typeof n&&Bt(e).css("padding-right",n).removeData("padding-right")}),Bt(re.STICKY_CONTENT+", "+re.NAVBAR_TOGGLER).each(function(t,e){var n=Bt(e).data("margin-right");"undefined"!=typeof n&&Bt(e).css("margin-right",n).removeData("margin-right")});var t=Bt(document.body).data("padding-right");"undefined"!=typeof t&&Bt(document.body).css("padding-right",t).removeData("padding-right")},t._getScrollbarWidth=function(){var t=document.createElement("div");t.className=$t,document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},r._jQueryInterface=function(n,i){return this.each(function(){var t=Bt(this).data(Gt),e=h({},r.Default,Bt(this).data(),"object"==typeof n&&n);if(t||(t=new r(this,e),Bt(this).data(Gt,t)),"string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n](i)}else e.show&&t.show(i)})},o(r,null,[{key:"VERSION",get:function(){return"4.1.0"}},{key:"Default",get:function(){return Xt}}]),r}(),Bt(document).on(Zt.CLICK_DATA_API,re.DATA_TOGGLE,function(t){var e,n=this,i=Cn.getSelectorFromElement(this);i&&(e=Bt(i)[0]);var r=Bt(e).data(Gt)?"toggle":h({},Bt(e).data(),Bt(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var s=Bt(e).one(Zt.SHOW,function(t){t.isDefaultPrevented()||s.one(Zt.HIDDEN,function(){Bt(n).is(":visible")&&n.focus()})});se._jQueryInterface.call(Bt(e),r,this)}),Bt.fn[Yt]=se._jQueryInterface,Bt.fn[Yt].Constructor=se,Bt.fn[Yt].noConflict=function(){return Bt.fn[Yt]=zt,se._jQueryInterface},se),Nn=(ae="tooltip",he="."+(le="bs.tooltip"),ce=(oe=e).fn[ae],ue="bs-tooltip",fe=new RegExp("(^|\\s)"+ue+"\\S+","g"),ge={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!(_e={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"}),selector:!(de={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)"}),placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent"},pe="out",ve={HIDE:"hide"+he,HIDDEN:"hidden"+he,SHOW:(me="show")+he,SHOWN:"shown"+he,INSERTED:"inserted"+he,CLICK:"click"+he,FOCUSIN:"focusin"+he,FOCUSOUT:"focusout"+he,MOUSEENTER:"mouseenter"+he,MOUSELEAVE:"mouseleave"+he},Ee="fade",ye="show",Te=".tooltip-inner",Ce=".arrow",Ie="hover",Ae="focus",De="click",be="manual",Se=function(){function i(t,e){if("undefined"==typeof c)throw new TypeError("Bootstrap tooltips require Popper.js (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=oe(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),oe(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(oe(this.getTipElement()).hasClass(ye))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),oe.removeData(this.element,this.constructor.DATA_KEY),oe(this.element).off(this.constructor.EVENT_KEY),oe(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&oe(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===oe(this.element).css("display"))throw new Error("Please use show on visible elements");var t=oe.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){oe(this.element).trigger(t);var n=oe.contains(this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!n)return;var i=this.getTipElement(),r=Cn.getUID(this.constructor.NAME);i.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&oe(i).addClass(Ee);var s="function"==typeof this.config.placement?this.config.placement.call(this,i,this.element):this.config.placement,o=this._getAttachment(s);this.addAttachmentClass(o);var a=!1===this.config.container?document.body:oe(this.config.container);oe(i).data(this.constructor.DATA_KEY,this),oe.contains(this.element.ownerDocument.documentElement,this.tip)||oe(i).appendTo(a),oe(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new c(this.element,i,{placement:o,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:Ce},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){e._handlePopperPlacementChange(t)}}),oe(i).addClass(ye),"ontouchstart"in document.documentElement&&oe(document.body).children().on("mouseover",null,oe.noop);var l=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,oe(e.element).trigger(e.constructor.Event.SHOWN),t===pe&&e._leave(null,e)};if(oe(this.tip).hasClass(Ee)){var h=Cn.getTransitionDurationFromElement(this.tip);oe(this.tip).one(Cn.TRANSITION_END,l).emulateTransitionEnd(h)}else l()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=oe.Event(this.constructor.Event.HIDE),r=function(){e._hoverState!==me&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),oe(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(oe(this.element).trigger(i),!i.isDefaultPrevented()){if(oe(n).removeClass(ye),"ontouchstart"in document.documentElement&&oe(document.body).children().off("mouseover",null,oe.noop),this._activeTrigger[De]=!1,this._activeTrigger[Ae]=!1,this._activeTrigger[Ie]=!1,oe(this.tip).hasClass(Ee)){var s=Cn.getTransitionDurationFromElement(n);oe(n).one(Cn.TRANSITION_END,r).emulateTransitionEnd(s)}else r();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){oe(this.getTipElement()).addClass(ue+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||oe(this.config.template)[0],this.tip},t.setContent=function(){var t=oe(this.getTipElement());this.setElementContent(t.find(Te),this.getTitle()),t.removeClass(Ee+" "+ye)},t.setElementContent=function(t,e){var n=this.config.html;"object"==typeof e&&(e.nodeType||e.jquery)?n?oe(e).parent().is(t)||t.empty().append(e):t.text(oe(e).text()):t[n?"html":"text"](e)},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getAttachment=function(t){return _e[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)oe(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==be){var e=t===Ie?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===Ie?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;oe(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}oe(i.element).closest(".modal").on("hide.bs.modal",function(){return i.hide()})}),this.config.selector?this.config=h({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||oe(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),oe(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Ae:Ie]=!0),oe(e.getTipElement()).hasClass(ye)||e._hoverState===me?e._hoverState=me:(clearTimeout(e._timeout),e._hoverState=me,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===me&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||oe(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),oe(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Ae:Ie]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=pe,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===pe&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){return"number"==typeof(t=h({},this.constructor.Default,oe(this.element).data(),t)).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),Cn.typeCheckConfig(ae,t,this.constructor.DefaultType),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=oe(this.getTipElement()),e=t.attr("class").match(fe);null!==e&&0<e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(oe(t).removeClass(Ee),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=oe(this).data(le),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),oe(this).data(le,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},o(i,null,[{key:"VERSION",get:function(){return"4.1.0"}},{key:"Default",get:function(){return ge}},{key:"NAME",get:function(){return ae}},{key:"DATA_KEY",get:function(){return le}},{key:"Event",get:function(){return ve}},{key:"EVENT_KEY",get:function(){return he}},{key:"DefaultType",get:function(){return de}}]),i}(),oe.fn[ae]=Se._jQueryInterface,oe.fn[ae].Constructor=Se,oe.fn[ae].noConflict=function(){return oe.fn[ae]=ce,Se._jQueryInterface},Se),On=(Ne="popover",ke="."+(Oe="bs.popover"),Pe=(we=e).fn[Ne],Le="bs-popover",je=new RegExp("(^|\\s)"+Le+"\\S+","g"),Re=h({},Nn.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),He=h({},Nn.DefaultType,{content:"(string|element|function)"}),We="fade",xe=".popover-header",Ue=".popover-body",Ke={HIDE:"hide"+ke,HIDDEN:"hidden"+ke,SHOW:(Me="show")+ke,SHOWN:"shown"+ke,INSERTED:"inserted"+ke,CLICK:"click"+ke,FOCUSIN:"focusin"+ke,FOCUSOUT:"focusout"+ke,MOUSEENTER:"mouseenter"+ke,MOUSELEAVE:"mouseleave"+ke},Fe=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var r=i.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(t){we(this.getTipElement()).addClass(Le+"-"+t)},r.getTipElement=function(){return this.tip=this.tip||we(this.config.template)[0],this.tip},r.setContent=function(){var t=we(this.getTipElement());this.setElementContent(t.find(xe),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(Ue),e),t.removeClass(We+" "+Me)},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var t=we(this.getTipElement()),e=t.attr("class").match(je);null!==e&&0<e.length&&t.removeClass(e.join(""))},i._jQueryInterface=function(n){return this.each(function(){var t=we(this).data(Oe),e="object"==typeof n?n:null;if((t||!/destroy|hide/.test(n))&&(t||(t=new i(this,e),we(this).data(Oe,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},o(i,null,[{key:"VERSION",get:function(){return"4.1.0"}},{key:"Default",get:function(){return Re}},{key:"NAME",get:function(){return Ne}},{key:"DATA_KEY",get:function(){return Oe}},{key:"Event",get:function(){return Ke}},{key:"EVENT_KEY",get:function(){return ke}},{key:"DefaultType",get:function(){return He}}]),i}(Nn),we.fn[Ne]=Fe._jQueryInterface,we.fn[Ne].Constructor=Fe,we.fn[Ne].noConflict=function(){return we.fn[Ne]=Pe,Fe._jQueryInterface},Fe),kn=(Qe="scrollspy",Ye="."+(Be="bs.scrollspy"),Ge=(Ve=e).fn[Qe],qe={offset:10,method:"auto",target:""},ze={offset:"number",method:"string",target:"(string|element)"},Xe={ACTIVATE:"activate"+Ye,SCROLL:"scroll"+Ye,LOAD_DATA_API:"load"+Ye+".data-api"},Je="dropdown-item",Ze="active",$e={DATA_SPY:'[data-spy="scroll"]',ACTIVE:".active",NAV_LIST_GROUP:".nav, .list-group",NAV_LINKS:".nav-link",NAV_ITEMS:".nav-item",LIST_ITEMS:".list-group-item",DROPDOWN:".dropdown",DROPDOWN_ITEMS:".dropdown-item",DROPDOWN_TOGGLE:".dropdown-toggle"},tn="offset",en="position",nn=function(){function n(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" "+$e.NAV_LINKS+","+this._config.target+" "+$e.LIST_ITEMS+","+this._config.target+" "+$e.DROPDOWN_ITEMS,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,Ve(this._scrollElement).on(Xe.SCROLL,function(t){return n._process(t)}),this.refresh(),this._process()}var t=n.prototype;return t.refresh=function(){var e=this,t=this._scrollElement===this._scrollElement.window?tn:en,r="auto"===this._config.method?t:this._config.method,s=r===en?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),Ve.makeArray(Ve(this._selector)).map(function(t){var e,n=Cn.getSelectorFromElement(t);if(n&&(e=Ve(n)[0]),e){var i=e.getBoundingClientRect();if(i.width||i.height)return[Ve(e)[r]().top+s,n]}return null}).filter(function(t){return t}).sort(function(t,e){return t[0]-e[0]}).forEach(function(t){e._offsets.push(t[0]),e._targets.push(t[1])})},t.dispose=function(){Ve.removeData(this._element,Be),Ve(this._scrollElement).off(Ye),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},t._getConfig=function(t){if("string"!=typeof(t=h({},qe,t)).target){var e=Ve(t.target).attr("id");e||(e=Cn.getUID(Qe),Ve(t.target).attr("id",e)),t.target="#"+e}return Cn.typeCheckConfig(Qe,t,ze),t},t._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},t._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},t._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},t._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),n<=t){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&0<this._offsets[0])return this._activeTarget=null,void this._clear();for(var r=this._offsets.length;r--;){this._activeTarget!==this._targets[r]&&t>=this._offsets[r]&&("undefined"==typeof this._offsets[r+1]||t<this._offsets[r+1])&&this._activate(this._targets[r])}}},t._activate=function(e){this._activeTarget=e,this._clear();var t=this._selector.split(",");t=t.map(function(t){return t+'[data-target="'+e+'"],'+t+'[href="'+e+'"]'});var n=Ve(t.join(","));n.hasClass(Je)?(n.closest($e.DROPDOWN).find($e.DROPDOWN_TOGGLE).addClass(Ze),n.addClass(Ze)):(n.addClass(Ze),n.parents($e.NAV_LIST_GROUP).prev($e.NAV_LINKS+", "+$e.LIST_ITEMS).addClass(Ze),n.parents($e.NAV_LIST_GROUP).prev($e.NAV_ITEMS).children($e.NAV_LINKS).addClass(Ze)),Ve(this._scrollElement).trigger(Xe.ACTIVATE,{relatedTarget:e})},t._clear=function(){Ve(this._selector).filter($e.ACTIVE).removeClass(Ze)},n._jQueryInterface=function(e){return this.each(function(){var t=Ve(this).data(Be);if(t||(t=new n(this,"object"==typeof e&&e),Ve(this).data(Be,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},o(n,null,[{key:"VERSION",get:function(){return"4.1.0"}},{key:"Default",get:function(){return qe}}]),n}(),Ve(window).on(Xe.LOAD_DATA_API,function(){for(var t=Ve.makeArray(Ve($e.DATA_SPY)),e=t.length;e--;){var n=Ve(t[e]);nn._jQueryInterface.call(n,n.data())}}),Ve.fn[Qe]=nn._jQueryInterface,Ve.fn[Qe].Constructor=nn,Ve.fn[Qe].noConflict=function(){return Ve.fn[Qe]=Ge,nn._jQueryInterface},nn),Pn=(on="."+(sn="bs.tab"),an=(rn=e).fn.tab,ln={HIDE:"hide"+on,HIDDEN:"hidden"+on,SHOW:"show"+on,SHOWN:"shown"+on,CLICK_DATA_API:"click"+on+".data-api"},hn="dropdown-menu",cn="active",un="disabled",fn="fade",dn="show",_n=".dropdown",gn=".nav, .list-group",mn=".active",pn="> li > .active",vn='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',En=".dropdown-toggle",yn="> .dropdown-menu .active",Tn=function(){function i(t){this._element=t}var t=i.prototype;return t.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&rn(this._element).hasClass(cn)||rn(this._element).hasClass(un))){var t,i,e=rn(this._element).closest(gn)[0],r=Cn.getSelectorFromElement(this._element);if(e){var s="UL"===e.nodeName?pn:mn;i=(i=rn.makeArray(rn(e).find(s)))[i.length-1]}var o=rn.Event(ln.HIDE,{relatedTarget:this._element}),a=rn.Event(ln.SHOW,{relatedTarget:i});if(i&&rn(i).trigger(o),rn(this._element).trigger(a),!a.isDefaultPrevented()&&!o.isDefaultPrevented()){r&&(t=rn(r)[0]),this._activate(this._element,e);var l=function(){var t=rn.Event(ln.HIDDEN,{relatedTarget:n._element}),e=rn.Event(ln.SHOWN,{relatedTarget:i});rn(i).trigger(t),rn(n._element).trigger(e)};t?this._activate(t,t.parentNode,l):l()}}},t.dispose=function(){rn.removeData(this._element,sn),this._element=null},t._activate=function(t,e,n){var i=this,r=("UL"===e.nodeName?rn(e).find(pn):rn(e).children(mn))[0],s=n&&r&&rn(r).hasClass(fn),o=function(){return i._transitionComplete(t,r,n)};if(r&&s){var a=Cn.getTransitionDurationFromElement(r);rn(r).one(Cn.TRANSITION_END,o).emulateTransitionEnd(a)}else o()},t._transitionComplete=function(t,e,n){if(e){rn(e).removeClass(dn+" "+cn);var i=rn(e.parentNode).find(yn)[0];i&&rn(i).removeClass(cn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(rn(t).addClass(cn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),Cn.reflow(t),rn(t).addClass(dn),t.parentNode&&rn(t.parentNode).hasClass(hn)){var r=rn(t).closest(_n)[0];r&&rn(r).find(En).addClass(cn),t.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var t=rn(this),e=t.data(sn);if(e||(e=new i(this),t.data(sn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}})},o(i,null,[{key:"VERSION",get:function(){return"4.1.0"}}]),i}(),rn(document).on(ln.CLICK_DATA_API,vn,function(t){t.preventDefault(),Tn._jQueryInterface.call(rn(this),"show")}),rn.fn.tab=Tn._jQueryInterface,rn.fn.tab.Constructor=Tn,rn.fn.tab.noConflict=function(){return rn.fn.tab=an,Tn._jQueryInterface},Tn);!function(t){if("undefined"==typeof t)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var e=t.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1===e[0]&&9===e[1]&&e[2]<1||4<=e[0])throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(e),t.Util=Cn,t.Alert=In,t.Button=An,t.Carousel=Dn,t.Collapse=bn,t.Dropdown=Sn,t.Modal=wn,t.Popover=On,t.Scrollspy=kn,t.Tab=Pn,t.Tooltip=Nn,Object.defineProperty(t,"__esModule",{value:!0})});
7
  //# sourceMappingURL=bootstrap.min.js.map
1
  /*!
2
+ * Bootstrap v4.5.3 (https://getbootstrap.com/)
3
+ * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap={},t.jQuery,t.Popper)}(this,(function(t,e,n){"use strict";function i(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=i(e),a=i(n);function s(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function l(t,e,n){return e&&s(t.prototype,e),n&&s(t,n),t}function r(){return(r=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t}).apply(this,arguments)}function u(t){var e=this,n=!1;return o.default(this).one(d.TRANSITION_END,(function(){n=!0})),setTimeout((function(){n||d.triggerTransitionEnd(e)}),t),this}var d={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var e=o.default(t).css("transition-duration"),n=o.default(t).css("transition-delay"),i=parseFloat(e),a=parseFloat(n);return i||a?(e=e.split(",")[0],n=n.split(",")[0],1e3*(parseFloat(e)+parseFloat(n))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){o.default(t).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],a=e[i],s=a&&d.isElement(a)?"element":null===(l=a)||"undefined"==typeof l?""+l:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(o).test(s))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+o+'".')}var l},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?d.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if("undefined"==typeof o.default)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=o.default.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};d.jQueryDetection(),o.default.fn.emulateTransitionEnd=u,o.default.event.special[d.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(o.default(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var f="alert",c=o.default.fn[f],h=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){o.default.removeData(this._element,"bs.alert"),this._element=null},e._getRootElement=function(t){var e=d.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=o.default(t).closest(".alert")[0]),n},e._triggerCloseEvent=function(t){var e=o.default.Event("close.bs.alert");return o.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(o.default(t).removeClass("show"),o.default(t).hasClass("fade")){var n=d.getTransitionDurationFromElement(t);o.default(t).one(d.TRANSITION_END,(function(n){return e._destroyElement(t,n)})).emulateTransitionEnd(n)}else this._destroyElement(t)},e._destroyElement=function(t){o.default(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.alert");i||(i=new t(this),n.data("bs.alert",i)),"close"===e&&i[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}}]),t}();o.default(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',h._handleDismiss(new h)),o.default.fn[f]=h._jQueryInterface,o.default.fn[f].Constructor=h,o.default.fn[f].noConflict=function(){return o.default.fn[f]=c,h._jQueryInterface};var g=o.default.fn.button,m=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,n=o.default(this._element).closest('[data-toggle="buttons"]')[0];if(n){var i=this._element.querySelector('input:not([type="hidden"])');if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains("active"))t=!1;else{var a=n.querySelector(".active");a&&o.default(a).removeClass("active")}t&&("checkbox"!==i.type&&"radio"!==i.type||(i.checked=!this._element.classList.contains("active")),this.shouldAvoidTriggerChange||o.default(i).trigger("change")),i.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains("active")),t&&o.default(this._element).toggleClass("active"))},e.dispose=function(){o.default.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(e,n){return this.each((function(){var i=o.default(this),a=i.data("bs.button");a||(a=new t(this),i.data("bs.button",a)),a.shouldAvoidTriggerChange=n,"toggle"===e&&a[e]()}))},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}}]),t}();o.default(document).on("click.bs.button.data-api",'[data-toggle^="button"]',(function(t){var e=t.target,n=e;if(o.default(e).hasClass("btn")||(e=o.default(e).closest(".btn")[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var i=e.querySelector('input:not([type="hidden"])');if(i&&(i.hasAttribute("disabled")||i.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==n.tagName&&"LABEL"===e.tagName||m._jQueryInterface.call(o.default(e),"toggle","INPUT"===n.tagName)}})).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',(function(t){var e=o.default(t.target).closest(".btn")[0];o.default(e).toggleClass("focus",/^focus(in)?$/.test(t.type))})),o.default(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e<n;e++){var i=t[e],o=i.querySelector('input:not([type="hidden"])');o.checked||o.hasAttribute("checked")?i.classList.add("active"):i.classList.remove("active")}for(var a=0,s=(t=[].slice.call(document.querySelectorAll('[data-toggle="button"]'))).length;a<s;a++){var l=t[a];"true"===l.getAttribute("aria-pressed")?l.classList.add("active"):l.classList.remove("active")}})),o.default.fn.button=m._jQueryInterface,o.default.fn.button.Constructor=m,o.default.fn.button.noConflict=function(){return o.default.fn.button=g,m._jQueryInterface};var p="carousel",_=".bs.carousel",v=o.default.fn[p],b={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},y={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},E={TOUCH:"touch",PEN:"pen"},w=function(){function t(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(".carousel-indicators"),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var e=t.prototype;return e.next=function(){this._isSliding||this._slide("next")},e.nextWhenVisible=function(){var t=o.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide("prev")},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(d.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(".active.carousel-item");var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)o.default(this._element).one("slid.bs.carousel",(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var i=t>n?"next":"prev";this._slide(i,this._items[t])}},e.dispose=function(){o.default(this._element).off(_),o.default.removeData(this._element,"bs.carousel"),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=r({},b,t),d.typeCheckConfig(p,t,y),t},e._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&o.default(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&o.default(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&E[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},n=function(e){t._pointerEvent&&E[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};o.default(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(o.default(this._element).on("pointerdown.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(o.default(this._element).on("touchstart.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("touchmove.bs.carousel",(function(e){return function(e){e.originalEvent.touches&&e.originalEvent.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),o.default(this._element).on("touchend.bs.carousel",(function(t){return n(t)})))}},e._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),a=this._items.length-1;if((i&&0===o||n&&o===a)&&!this._config.wrap)return e;var s=(o+("prev"===t?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},e._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(".active.carousel-item")),a=o.default.Event("slide.bs.carousel",{relatedTarget:t,direction:e,from:i,to:n});return o.default(this._element).trigger(a),a},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));o.default(e).removeClass("active");var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&o.default(n).addClass("active")}},e._slide=function(t,e){var n,i,a,s=this,l=this._element.querySelector(".active.carousel-item"),r=this._getItemIndex(l),u=e||l&&this._getItemByDirection(t,l),f=this._getItemIndex(u),c=Boolean(this._interval);if("next"===t?(n="carousel-item-left",i="carousel-item-next",a="left"):(n="carousel-item-right",i="carousel-item-prev",a="right"),u&&o.default(u).hasClass("active"))this._isSliding=!1;else if(!this._triggerSlideEvent(u,a).isDefaultPrevented()&&l&&u){this._isSliding=!0,c&&this.pause(),this._setActiveIndicatorElement(u);var h=o.default.Event("slid.bs.carousel",{relatedTarget:u,direction:a,from:r,to:f});if(o.default(this._element).hasClass("slide")){o.default(u).addClass(i),d.reflow(u),o.default(l).addClass(n),o.default(u).addClass(n);var g=parseInt(u.getAttribute("data-interval"),10);g?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=g):this._config.interval=this._config.defaultInterval||this._config.interval;var m=d.getTransitionDurationFromElement(l);o.default(l).one(d.TRANSITION_END,(function(){o.default(u).removeClass(n+" "+i).addClass("active"),o.default(l).removeClass("active "+i+" "+n),s._isSliding=!1,setTimeout((function(){return o.default(s._element).trigger(h)}),0)})).emulateTransitionEnd(m)}else o.default(l).removeClass("active"),o.default(u).addClass("active"),this._isSliding=!1,o.default(this._element).trigger(h);c&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data("bs.carousel"),i=r({},b,o.default(this).data());"object"==typeof e&&(i=r({},i,e));var a="string"==typeof e?e:i.slide;if(n||(n=new t(this,i),o.default(this).data("bs.carousel",n)),"number"==typeof e)n.to(e);else if("string"==typeof a){if("undefined"==typeof n[a])throw new TypeError('No method named "'+a+'"');n[a]()}else i.interval&&i.ride&&(n.pause(),n.cycle())}))},t._dataApiClickHandler=function(e){var n=d.getSelectorFromElement(this);if(n){var i=o.default(n)[0];if(i&&o.default(i).hasClass("carousel")){var a=r({},o.default(i).data(),o.default(this).data()),s=this.getAttribute("data-slide-to");s&&(a.interval=!1),t._jQueryInterface.call(o.default(i),a),s&&o.default(i).data("bs.carousel").to(s),e.preventDefault()}}},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return b}}]),t}();o.default(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",w._dataApiClickHandler),o.default(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),e=0,n=t.length;e<n;e++){var i=o.default(t[e]);w._jQueryInterface.call(i,i.data())}})),o.default.fn[p]=w._jQueryInterface,o.default.fn[p].Constructor=w,o.default.fn[p].noConflict=function(){return o.default.fn[p]=v,w._jQueryInterface};var T="collapse",C=o.default.fn[T],S={toggle:!0,parent:""},N={toggle:"boolean",parent:"(string|element)"},D=function(){function t(t,e){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(e),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var n=[].slice.call(document.querySelectorAll('[data-toggle="collapse"]')),i=0,o=n.length;i<o;i++){var a=n[i],s=d.getSelectorFromElement(a),l=[].slice.call(document.querySelectorAll(s)).filter((function(e){return e===t}));null!==s&&l.length>0&&(this._selector=s,this._triggerArray.push(a))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){o.default(this._element).hasClass("show")?this.hide():this.show()},e.show=function(){var e,n,i=this;if(!this._isTransitioning&&!o.default(this._element).hasClass("show")&&(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof i._config.parent?t.getAttribute("data-parent")===i._config.parent:t.classList.contains("collapse")}))).length&&(e=null),!(e&&(n=o.default(e).not(this._selector).data("bs.collapse"))&&n._isTransitioning))){var a=o.default.Event("show.bs.collapse");if(o.default(this._element).trigger(a),!a.isDefaultPrevented()){e&&(t._jQueryInterface.call(o.default(e).not(this._selector),"hide"),n||o.default(e).data("bs.collapse",null));var s=this._getDimension();o.default(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[s]=0,this._triggerArray.length&&o.default(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var l="scroll"+(s[0].toUpperCase()+s.slice(1)),r=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,(function(){o.default(i._element).removeClass("collapsing").addClass("collapse show"),i._element.style[s]="",i.setTransitioning(!1),o.default(i._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(r),this._element.style[s]=this._element[l]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&o.default(this._element).hasClass("show")){var e=o.default.Event("hide.bs.collapse");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",d.reflow(this._element),o.default(this._element).addClass("collapsing").removeClass("collapse show");var i=this._triggerArray.length;if(i>0)for(var a=0;a<i;a++){var s=this._triggerArray[a],l=d.getSelectorFromElement(s);if(null!==l)o.default([].slice.call(document.querySelectorAll(l))).hasClass("show")||o.default(s).addClass("collapsed").attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[n]="";var r=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,(function(){t.setTransitioning(!1),o.default(t._element).removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")})).emulateTransitionEnd(r)}}},e.setTransitioning=function(t){this._isTransitioning=t},e.dispose=function(){o.default.removeData(this._element,"bs.collapse"),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},e._getConfig=function(t){return(t=r({},S,t)).toggle=Boolean(t.toggle),d.typeCheckConfig(T,t,N),t},e._getDimension=function(){return o.default(this._element).hasClass("width")?"width":"height"},e._getParent=function(){var e,n=this;d.isElement(this._config.parent)?(e=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(e=this._config.parent[0])):e=document.querySelector(this._config.parent);var i='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',a=[].slice.call(e.querySelectorAll(i));return o.default(a).each((function(e,i){n._addAriaAndCollapsedClass(t._getTargetFromElement(i),[i])})),e},e._addAriaAndCollapsedClass=function(t,e){var n=o.default(t).hasClass("show");e.length&&o.default(e).toggleClass("collapsed",!n).attr("aria-expanded",n)},t._getTargetFromElement=function(t){var e=d.getSelectorFromElement(t);return e?document.querySelector(e):null},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.collapse"),a=r({},S,n.data(),"object"==typeof e&&e?e:{});if(!i&&a.toggle&&"string"==typeof e&&/show|hide/.test(e)&&(a.toggle=!1),i||(i=new t(this,a),n.data("bs.collapse",i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return S}}]),t}();o.default(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',(function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var e=o.default(this),n=d.getSelectorFromElement(this),i=[].slice.call(document.querySelectorAll(n));o.default(i).each((function(){var t=o.default(this),n=t.data("bs.collapse")?"toggle":e.data();D._jQueryInterface.call(t,n)}))})),o.default.fn[T]=D._jQueryInterface,o.default.fn[T].Constructor=D,o.default.fn[T].noConflict=function(){return o.default.fn[T]=C,D._jQueryInterface};var k="dropdown",A=o.default.fn[k],I=new RegExp("38|40|27"),j={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic",popperConfig:null},O={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string",popperConfig:"(null|object)"},x=function(){function t(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var e=t.prototype;return e.toggle=function(){if(!this._element.disabled&&!o.default(this._element).hasClass("disabled")){var e=o.default(this._menu).hasClass("show");t._clearMenus(),e||this.show(!0)}},e.show=function(e){if(void 0===e&&(e=!1),!(this._element.disabled||o.default(this._element).hasClass("disabled")||o.default(this._menu).hasClass("show"))){var n={relatedTarget:this._element},i=o.default.Event("show.bs.dropdown",n),s=t._getParentFromElement(this._element);if(o.default(s).trigger(i),!i.isDefaultPrevented()){if(!this._inNavbar&&e){if("undefined"==typeof a.default)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var l=this._element;"parent"===this._config.reference?l=s:d.isElement(this._config.reference)&&(l=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(l=this._config.reference[0])),"scrollParent"!==this._config.boundary&&o.default(s).addClass("position-static"),this._popper=new a.default(l,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===o.default(s).closest(".navbar-nav").length&&o.default(document.body).children().on("mouseover",null,o.default.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),o.default(this._menu).toggleClass("show"),o.default(s).toggleClass("show").trigger(o.default.Event("shown.bs.dropdown",n))}}},e.hide=function(){if(!this._element.disabled&&!o.default(this._element).hasClass("disabled")&&o.default(this._menu).hasClass("show")){var e={relatedTarget:this._element},n=o.default.Event("hide.bs.dropdown",e),i=t._getParentFromElement(this._element);o.default(i).trigger(n),n.isDefaultPrevented()||(this._popper&&this._popper.destroy(),o.default(this._menu).toggleClass("show"),o.default(i).toggleClass("show").trigger(o.default.Event("hidden.bs.dropdown",e)))}},e.dispose=function(){o.default.removeData(this._element,"bs.dropdown"),o.default(this._element).off(".bs.dropdown"),this._element=null,this._menu=null,null!==this._popper&&(this._popper.destroy(),this._popper=null)},e.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},e._addEventListeners=function(){var t=this;o.default(this._element).on("click.bs.dropdown",(function(e){e.preventDefault(),e.stopPropagation(),t.toggle()}))},e._getConfig=function(t){return t=r({},this.constructor.Default,o.default(this._element).data(),t),d.typeCheckConfig(k,t,this.constructor.DefaultType),t},e._getMenuElement=function(){if(!this._menu){var e=t._getParentFromElement(this._element);e&&(this._menu=e.querySelector(".dropdown-menu"))}return this._menu},e._getPlacement=function(){var t=o.default(this._element.parentNode),e="bottom-start";return t.hasClass("dropup")?e=o.default(this._menu).hasClass("dropdown-menu-right")?"top-end":"top-start":t.hasClass("dropright")?e="right-start":t.hasClass("dropleft")?e="left-start":o.default(this._menu).hasClass("dropdown-menu-right")&&(e="bottom-end"),e},e._detectNavbar=function(){return o.default(this._element).closest(".navbar").length>0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t._config.offset(e.offsets,t._element)||{}),e}:e.offset=this._config.offset,e},e._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),r({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data("bs.dropdown");if(n||(n=new t(this,"object"==typeof e?e:null),o.default(this).data("bs.dropdown",n)),"string"==typeof e){if("undefined"==typeof n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},t._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var n=[].slice.call(document.querySelectorAll('[data-toggle="dropdown"]')),i=0,a=n.length;i<a;i++){var s=t._getParentFromElement(n[i]),l=o.default(n[i]).data("bs.dropdown"),r={relatedTarget:n[i]};if(e&&"click"===e.type&&(r.clickEvent=e),l){var u=l._menu;if(o.default(s).hasClass("show")&&!(e&&("click"===e.type&&/input|textarea/i.test(e.target.tagName)||"keyup"===e.type&&9===e.which)&&o.default.contains(s,e.target))){var d=o.default.Event("hide.bs.dropdown",r);o.default(s).trigger(d),d.isDefaultPrevented()||("ontouchstart"in document.documentElement&&o.default(document.body).children().off("mouseover",null,o.default.noop),n[i].setAttribute("aria-expanded","false"),l._popper&&l._popper.destroy(),o.default(u).removeClass("show"),o.default(s).removeClass("show").trigger(o.default.Event("hidden.bs.dropdown",r)))}}}},t._getParentFromElement=function(t){var e,n=d.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},t._dataApiKeydownHandler=function(e){if(!(/input|textarea/i.test(e.target.tagName)?32===e.which||27!==e.which&&(40!==e.which&&38!==e.which||o.default(e.target).closest(".dropdown-menu").length):!I.test(e.which))&&!this.disabled&&!o.default(this).hasClass("disabled")){var n=t._getParentFromElement(this),i=o.default(n).hasClass("show");if(i||27!==e.which){if(e.preventDefault(),e.stopPropagation(),!i||27===e.which||32===e.which)return 27===e.which&&o.default(n.querySelector('[data-toggle="dropdown"]')).trigger("focus"),void o.default(this).trigger("click");var a=[].slice.call(n.querySelectorAll(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)")).filter((function(t){return o.default(t).is(":visible")}));if(0!==a.length){var s=a.indexOf(e.target);38===e.which&&s>0&&s--,40===e.which&&s<a.length-1&&s++,s<0&&(s=0),a[s].focus()}}}},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return j}},{key:"DefaultType",get:function(){return O}}]),t}();o.default(document).on("keydown.bs.dropdown.data-api",'[data-toggle="dropdown"]',x._dataApiKeydownHandler).on("keydown.bs.dropdown.data-api",".dropdown-menu",x._dataApiKeydownHandler).on("click.bs.dropdown.data-api keyup.bs.dropdown.data-api",x._clearMenus).on("click.bs.dropdown.data-api",'[data-toggle="dropdown"]',(function(t){t.preventDefault(),t.stopPropagation(),x._jQueryInterface.call(o.default(this),"toggle")})).on("click.bs.dropdown.data-api",".dropdown form",(function(t){t.stopPropagation()})),o.default.fn[k]=x._jQueryInterface,o.default.fn[k].Constructor=x,o.default.fn[k].noConflict=function(){return o.default.fn[k]=A,x._jQueryInterface};var P=o.default.fn.modal,R={backdrop:!0,keyboard:!0,focus:!0,show:!0},L={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},q=function(){function t(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(".modal-dialog"),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var e=t.prototype;return e.toggle=function(t){return this._isShown?this.hide():this.show(t)},e.show=function(t){var e=this;if(!this._isShown&&!this._isTransitioning){o.default(this._element).hasClass("fade")&&(this._isTransitioning=!0);var n=o.default.Event("show.bs.modal",{relatedTarget:t});o.default(this._element).trigger(n),this._isShown||n.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),o.default(this._element).on("click.dismiss.bs.modal",'[data-dismiss="modal"]',(function(t){return e.hide(t)})),o.default(this._dialog).on("mousedown.dismiss.bs.modal",(function(){o.default(e._element).one("mouseup.dismiss.bs.modal",(function(t){o.default(t.target).is(e._element)&&(e._ignoreBackdropClick=!0)}))})),this._showBackdrop((function(){return e._showElement(t)})))}},e.hide=function(t){var e=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var n=o.default.Event("hide.bs.modal");if(o.default(this._element).trigger(n),this._isShown&&!n.isDefaultPrevented()){this._isShown=!1;var i=o.default(this._element).hasClass("fade");if(i&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),o.default(document).off("focusin.bs.modal"),o.default(this._element).removeClass("show"),o.default(this._element).off("click.dismiss.bs.modal"),o.default(this._dialog).off("mousedown.dismiss.bs.modal"),i){var a=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,(function(t){return e._hideModal(t)})).emulateTransitionEnd(a)}else this._hideModal()}}},e.dispose=function(){[window,this._element,this._dialog].forEach((function(t){return o.default(t).off(".bs.modal")})),o.default(document).off("focusin.bs.modal"),o.default.removeData(this._element,"bs.modal"),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},e.handleUpdate=function(){this._adjustDialog()},e._getConfig=function(t){return t=r({},R,t),d.typeCheckConfig("modal",t,L),t},e._triggerBackdropTransition=function(){var t=this;if("static"===this._config.backdrop){var e=o.default.Event("hidePrevented.bs.modal");if(o.default(this._element).trigger(e),e.isDefaultPrevented())return;var n=this._element.scrollHeight>document.documentElement.clientHeight;n||(this._element.style.overflowY="hidden"),this._element.classList.add("modal-static");var i=d.getTransitionDurationFromElement(this._dialog);o.default(this._element).off(d.TRANSITION_END),o.default(this._element).one(d.TRANSITION_END,(function(){t._element.classList.remove("modal-static"),n||o.default(t._element).one(d.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,i)})).emulateTransitionEnd(i),this._element.focus()}else this.hide()},e._showElement=function(t){var e=this,n=o.default(this._element).hasClass("fade"),i=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),o.default(this._dialog).hasClass("modal-dialog-scrollable")&&i?i.scrollTop=0:this._element.scrollTop=0,n&&d.reflow(this._element),o.default(this._element).addClass("show"),this._config.focus&&this._enforceFocus();var a=o.default.Event("shown.bs.modal",{relatedTarget:t}),s=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,o.default(e._element).trigger(a)};if(n){var l=d.getTransitionDurationFromElement(this._dialog);o.default(this._dialog).one(d.TRANSITION_END,s).emulateTransitionEnd(l)}else s()},e._enforceFocus=function(){var t=this;o.default(document).off("focusin.bs.modal").on("focusin.bs.modal",(function(e){document!==e.target&&t._element!==e.target&&0===o.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?o.default(this._element).on("keydown.dismiss.bs.modal",(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||o.default(this._element).off("keydown.dismiss.bs.modal")},e._setResizeEvent=function(){var t=this;this._isShown?o.default(window).on("resize.bs.modal",(function(e){return t.handleUpdate(e)})):o.default(window).off("resize.bs.modal")},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){o.default(document.body).removeClass("modal-open"),t._resetAdjustments(),t._resetScrollbar(),o.default(t._element).trigger("hidden.bs.modal")}))},e._removeBackdrop=function(){this._backdrop&&(o.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,n=o.default(this._element).hasClass("fade")?"fade":"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",n&&this._backdrop.classList.add(n),o.default(this._backdrop).appendTo(document.body),o.default(this._element).on("click.dismiss.bs.modal",(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&e._triggerBackdropTransition()})),n&&d.reflow(this._backdrop),o.default(this._backdrop).addClass("show"),!t)return;if(!n)return void t();var i=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){o.default(this._backdrop).removeClass("show");var a=function(){e._removeBackdrop(),t&&t()};if(o.default(this._element).hasClass("fade")){var s=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},e._setScrollbar=function(){var t=this;if(this._isBodyOverflowing){var e=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top")),n=[].slice.call(document.querySelectorAll(".sticky-top"));o.default(e).each((function(e,n){var i=n.style.paddingRight,a=o.default(n).css("padding-right");o.default(n).data("padding-right",i).css("padding-right",parseFloat(a)+t._scrollbarWidth+"px")})),o.default(n).each((function(e,n){var i=n.style.marginRight,a=o.default(n).css("margin-right");o.default(n).data("margin-right",i).css("margin-right",parseFloat(a)-t._scrollbarWidth+"px")}));var i=document.body.style.paddingRight,a=o.default(document.body).css("padding-right");o.default(document.body).data("padding-right",i).css("padding-right",parseFloat(a)+this._scrollbarWidth+"px")}o.default(document.body).addClass("modal-open")},e._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top"));o.default(t).each((function(t,e){var n=o.default(e).data("padding-right");o.default(e).removeData("padding-right"),e.style.paddingRight=n||""}));var e=[].slice.call(document.querySelectorAll(".sticky-top"));o.default(e).each((function(t,e){var n=o.default(e).data("margin-right");"undefined"!=typeof n&&o.default(e).css("margin-right",n).removeData("margin-right")}));var n=o.default(document.body).data("padding-right");o.default(document.body).removeData("padding-right"),document.body.style.paddingRight=n||""},e._getScrollbarWidth=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},t._jQueryInterface=function(e,n){return this.each((function(){var i=o.default(this).data("bs.modal"),a=r({},R,o.default(this).data(),"object"==typeof e&&e?e:{});if(i||(i=new t(this,a),o.default(this).data("bs.modal",i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e](n)}else a.show&&i.show(n)}))},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return R}}]),t}();o.default(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',(function(t){var e,n=this,i=d.getSelectorFromElement(this);i&&(e=document.querySelector(i));var a=o.default(e).data("bs.modal")?"toggle":r({},o.default(e).data(),o.default(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var s=o.default(e).one("show.bs.modal",(function(t){t.isDefaultPrevented()||s.one("hidden.bs.modal",(function(){o.default(n).is(":visible")&&n.focus()}))}));q._jQueryInterface.call(o.default(e),a,this)})),o.default.fn.modal=q._jQueryInterface,o.default.fn.modal.Constructor=q,o.default.fn.modal.noConflict=function(){return o.default.fn.modal=P,q._jQueryInterface};var F=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],Q={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},B=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi,H=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;function U(t,e,n){if(0===t.length)return t;if(n&&"function"==typeof n)return n(t);for(var i=(new window.DOMParser).parseFromString(t,"text/html"),o=Object.keys(e),a=[].slice.call(i.body.querySelectorAll("*")),s=function(t,n){var i=a[t],s=i.nodeName.toLowerCase();if(-1===o.indexOf(i.nodeName.toLowerCase()))return i.parentNode.removeChild(i),"continue";var l=[].slice.call(i.attributes),r=[].concat(e["*"]||[],e[s]||[]);l.forEach((function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===F.indexOf(n)||Boolean(t.nodeValue.match(B)||t.nodeValue.match(H));for(var i=e.filter((function(t){return t instanceof RegExp})),o=0,a=i.length;o<a;o++)if(n.match(i[o]))return!0;return!1})(t,r)||i.removeAttribute(t.nodeName)}))},l=0,r=a.length;l<r;l++)s(l);return i.body.innerHTML}var M="tooltip",W=o.default.fn[M],V=new RegExp("(^|\\s)bs-tooltip\\S+","g"),z=["sanitize","whiteList","sanitizeFn"],K={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},X={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},Y={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Q,popperConfig:null},$={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},J=function(){function t(t,e){if("undefined"==typeof a.default)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=o.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(o.default(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),o.default.removeData(this.element,this.constructor.DATA_KEY),o.default(this.element).off(this.constructor.EVENT_KEY),o.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&o.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===o.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=o.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){o.default(this.element).trigger(e);var n=d.findShadowRoot(this.element),i=o.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!i)return;var s=this.getTipElement(),l=d.getUID(this.constructor.NAME);s.setAttribute("id",l),this.element.setAttribute("aria-describedby",l),this.setContent(),this.config.animation&&o.default(s).addClass("fade");var r="function"==typeof this.config.placement?this.config.placement.call(this,s,this.element):this.config.placement,u=this._getAttachment(r);this.addAttachmentClass(u);var f=this._getContainer();o.default(s).data(this.constructor.DATA_KEY,this),o.default.contains(this.element.ownerDocument.documentElement,this.tip)||o.default(s).appendTo(f),o.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new a.default(this.element,s,this._getPopperConfig(u)),o.default(s).addClass("show"),"ontouchstart"in document.documentElement&&o.default(document.body).children().on("mouseover",null,o.default.noop);var c=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,o.default(t.element).trigger(t.constructor.Event.SHOWN),"out"===e&&t._leave(null,t)};if(o.default(this.tip).hasClass("fade")){var h=d.getTransitionDurationFromElement(this.tip);o.default(this.tip).one(d.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},e.hide=function(t){var e=this,n=this.getTipElement(),i=o.default.Event(this.constructor.Event.HIDE),a=function(){"show"!==e._hoverState&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),o.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(o.default(this.element).trigger(i),!i.isDefaultPrevented()){if(o.default(n).removeClass("show"),"ontouchstart"in document.documentElement&&o.default(document.body).children().off("mouseover",null,o.default.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,o.default(this.tip).hasClass("fade")){var s=d.getTransitionDurationFromElement(n);o.default(n).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-tooltip-"+t)},e.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(o.default(t.querySelectorAll(".tooltip-inner")),this.getTitle()),o.default(t).removeClass("fade show")},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=U(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?o.default(e).parent().is(t)||t.empty().append(e):t.text(o.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return r({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:d.isElement(this.config.container)?o.default(this.config.container):o.default(document).find(this.config.container)},e._getAttachment=function(t){return X[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)o.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n="hover"===e?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,i="hover"===e?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;o.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(i,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},o.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=r({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),o.default(e.getTipElement()).hasClass("show")||"show"===e._hoverState?e._hoverState="show":(clearTimeout(e._timeout),e._hoverState="show",e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){"show"===e._hoverState&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState="out",e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){"out"===e._hoverState&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=o.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==z.indexOf(t)&&delete e[t]})),"number"==typeof(t=r({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),d.typeCheckConfig(M,t,this.constructor.DefaultType),t.sanitize&&(t.template=U(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(V);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(o.default(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.tooltip"),a="object"==typeof e&&e;if((i||!/dispose|hide/.test(e))&&(i||(i=new t(this,a),n.data("bs.tooltip",i)),"string"==typeof e)){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return Y}},{key:"NAME",get:function(){return M}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return $}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return K}}]),t}();o.default.fn[M]=J._jQueryInterface,o.default.fn[M].Constructor=J,o.default.fn[M].noConflict=function(){return o.default.fn[M]=W,J._jQueryInterface};var G="popover",Z=o.default.fn[G],tt=new RegExp("(^|\\s)bs-popover\\S+","g"),et=r({},J.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),nt=r({},J.DefaultType,{content:"(string|element|function)"}),it={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},ot=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),e.prototype.constructor=e,e.__proto__=n;var a=i.prototype;return a.isWithContent=function(){return this.getTitle()||this._getContent()},a.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-popover-"+t)},a.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},a.setContent=function(){var t=o.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},a._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},a._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(tt);null!==e&&e.length>0&&t.removeClass(e.join(""))},i._jQueryInterface=function(t){return this.each((function(){var e=o.default(this).data("bs.popover"),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new i(this,n),o.default(this).data("bs.popover",e)),"string"==typeof t)){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},l(i,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return et}},{key:"NAME",get:function(){return G}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return it}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return nt}}]),i}(J);o.default.fn[G]=ot._jQueryInterface,o.default.fn[G].Constructor=ot,o.default.fn[G].noConflict=function(){return o.default.fn[G]=Z,ot._jQueryInterface};var at="scrollspy",st=o.default.fn[at],lt={offset:10,method:"auto",target:""},rt={offset:"number",method:"string",target:"(string|element)"},ut=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,o.default(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":"position",n="auto"===this._config.method?e:this._config.method,i="position"===n?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,a=d.getSelectorFromElement(t);if(a&&(e=document.querySelector(a)),e){var s=e.getBoundingClientRect();if(s.width||s.height)return[o.default(e)[n]().top+i,a]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){o.default.removeData(this._element,"bs.scrollspy"),o.default(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=r({},lt,"object"==typeof t&&t?t:{})).target&&d.isElement(t.target)){var e=o.default(t.target).attr("id");e||(e=d.getUID(at),o.default(t.target).attr("id",e)),t.target="#"+e}return d.typeCheckConfig(at,t,rt),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&this._offsets[0]>0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},e._activate=function(t){this._activeTarget=t,this._clear();var e=this._selector.split(",").map((function(e){return e+'[data-target="'+t+'"],'+e+'[href="'+t+'"]'})),n=o.default([].slice.call(document.querySelectorAll(e.join(","))));n.hasClass("dropdown-item")?(n.closest(".dropdown").find(".dropdown-toggle").addClass("active"),n.addClass("active")):(n.addClass("active"),n.parents(".nav, .list-group").prev(".nav-link, .list-group-item").addClass("active"),n.parents(".nav, .list-group").prev(".nav-item").children(".nav-link").addClass("active")),o.default(this._scrollElement).trigger("activate.bs.scrollspy",{relatedTarget:t})},e._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter((function(t){return t.classList.contains("active")})).forEach((function(t){return t.classList.remove("active")}))},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data("bs.scrollspy");if(n||(n=new t(this,"object"==typeof e&&e),o.default(this).data("bs.scrollspy",n)),"string"==typeof e){if("undefined"==typeof n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return lt}}]),t}();o.default(window).on("load.bs.scrollspy.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-spy="scroll"]')),e=t.length;e--;){var n=o.default(t[e]);ut._jQueryInterface.call(n,n.data())}})),o.default.fn[at]=ut._jQueryInterface,o.default.fn[at].Constructor=ut,o.default.fn[at].noConflict=function(){return o.default.fn[at]=st,ut._jQueryInterface};var dt=o.default.fn.tab,ft=function(){function t(t){this._element=t}var e=t.prototype;return e.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&o.default(this._element).hasClass("active")||o.default(this._element).hasClass("disabled"))){var e,n,i=o.default(this._element).closest(".nav, .list-group")[0],a=d.getSelectorFromElement(this._element);if(i){var s="UL"===i.nodeName||"OL"===i.nodeName?"> li > .active":".active";n=(n=o.default.makeArray(o.default(i).find(s)))[n.length-1]}var l=o.default.Event("hide.bs.tab",{relatedTarget:this._element}),r=o.default.Event("show.bs.tab",{relatedTarget:n});if(n&&o.default(n).trigger(l),o.default(this._element).trigger(r),!r.isDefaultPrevented()&&!l.isDefaultPrevented()){a&&(e=document.querySelector(a)),this._activate(this._element,i);var u=function(){var e=o.default.Event("hidden.bs.tab",{relatedTarget:t._element}),i=o.default.Event("shown.bs.tab",{relatedTarget:n});o.default(n).trigger(e),o.default(t._element).trigger(i)};e?this._activate(e,e.parentNode,u):u()}}},e.dispose=function(){o.default.removeData(this._element,"bs.tab"),this._element=null},e._activate=function(t,e,n){var i=this,a=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?o.default(e).children(".active"):o.default(e).find("> li > .active"))[0],s=n&&a&&o.default(a).hasClass("fade"),l=function(){return i._transitionComplete(t,a,n)};if(a&&s){var r=d.getTransitionDurationFromElement(a);o.default(a).removeClass("show").one(d.TRANSITION_END,l).emulateTransitionEnd(r)}else l()},e._transitionComplete=function(t,e,n){if(e){o.default(e).removeClass("active");var i=o.default(e.parentNode).find("> .dropdown-menu .active")[0];i&&o.default(i).removeClass("active"),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(o.default(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),d.reflow(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&o.default(t.parentNode).hasClass("dropdown-menu")){var a=o.default(t).closest(".dropdown")[0];if(a){var s=[].slice.call(a.querySelectorAll(".dropdown-toggle"));o.default(s).addClass("active")}t.setAttribute("aria-expanded",!0)}n&&n()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.tab");if(i||(i=new t(this),n.data("bs.tab",i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}}]),t}();o.default(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),ft._jQueryInterface.call(o.default(this),"show")})),o.default.fn.tab=ft._jQueryInterface,o.default.fn.tab.Constructor=ft,o.default.fn.tab.noConflict=function(){return o.default.fn.tab=dt,ft._jQueryInterface};var ct=o.default.fn.toast,ht={animation:"boolean",autohide:"boolean",delay:"number"},gt={animation:!0,autohide:!0,delay:500},mt=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var e=t.prototype;return e.show=function(){var t=this,e=o.default.Event("show.bs.toast");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var n=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),o.default(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),d.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var i=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,n).emulateTransitionEnd(i)}else n()}},e.hide=function(){if(this._element.classList.contains("show")){var t=o.default.Event("hide.bs.toast");o.default(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},e.dispose=function(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),o.default(this._element).off("click.dismiss.bs.toast"),o.default.removeData(this._element,"bs.toast"),this._element=null,this._config=null},e._getConfig=function(t){return t=r({},gt,o.default(this._element).data(),"object"==typeof t&&t?t:{}),d.typeCheckConfig("toast",t,this.constructor.DefaultType),t},e._setListeners=function(){var t=this;o.default(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},e._close=function(){var t=this,e=function(){t._element.classList.add("hide"),o.default(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var n=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},e._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data("bs.toast");if(i||(i=new t(this,"object"==typeof e&&e),n.data("bs.toast",i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e](this)}}))},l(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"DefaultType",get:function(){return ht}},{key:"Default",get:function(){return gt}}]),t}();o.default.fn.toast=mt._jQueryInterface,o.default.fn.toast.Constructor=mt,o.default.fn.toast.noConflict=function(){return o.default.fn.toast=ct,mt._jQueryInterface},t.Alert=h,t.Button=m,t.Carousel=w,t.Collapse=D,t.Dropdown=x,t.Modal=q,t.Popover=ot,t.Scrollspy=ut,t.Tab=ft,t.Toast=mt,t.Tooltip=J,t.Util=d,Object.defineProperty(t,"__esModule",{value:!0})}));
7
  //# sourceMappingURL=bootstrap.min.js.map
assets/js/jquery-ui.min.js DELETED
@@ -1,13 +0,0 @@
1
- /*! jQuery UI - v1.11.4 - 2015-03-11
2
- * http://jqueryui.com
3
- * Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js
4
- * Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
5
-
6
- (function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return"area"===r?(n=t.parentNode,a=n.name,t.href&&a&&"map"===n.nodeName.toLowerCase()?(o=e("img[usemap='#"+a+"']")[0],!!o&&i(o)):!1):(/^(input|select|textarea|button|object)$/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}function s(e){for(var t,i;e.length&&e[0]!==document;){if(t=e.css("position"),("absolute"===t||"relative"===t||"fixed"===t)&&(i=parseInt(e.css("zIndex"),10),!isNaN(i)&&0!==i))return i;e=e.parent()}return 0}function n(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.regional.en=e.extend(!0,{},this.regional[""]),this.regional["en-US"]=e.extend(!0,{},this.regional.en),this.dpDiv=a(e("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function a(t){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(i,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",o)}function o(){e.datepicker._isDisabledDatepicker(v.inline?v.dpDiv.parent()[0]:v.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))}function r(t,i){e.extend(t,i);for(var s in i)null==i[s]&&(t[s]=i[s]);return t}function h(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+"px")})},e.fn["outer"+i]=function(t,n){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var l=0,u=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,n=u.call(arguments,1),a=0,o=n.length;o>a;a++)for(i in n[a])s=n[a][i],n[a].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(n){var a="string"==typeof n,o=u.call(arguments,1),r=this;return a?this.each(function(){var i,a=e.data(this,s);return"instance"===n?(r=a,!1):a?e.isFunction(a[n])&&"_"!==n.charAt(0)?(i=a[n].apply(a,o),i!==a&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+n+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+n+"'")}):(o.length&&(n=e.widget.extend.apply(null,[n].concat(o))),this.each(function(){var t=e.data(this,s);t?(t.option(n||{}),t._init&&t._init()):e.data(this,s,new i(n,this))})),r}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=l++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget;var d=!1;e(document).mouseup(function(){d=!1}),e.widget("ui.mouse",{version:"1.11.4",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!d){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var i=this,s=1===t.which,n="string"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return i._mouseMove(e)},this._mouseUpDelegate=function(e){return i._mouseUp(e)},this.document.bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),d=!0,!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button)return this._mouseUp(t);if(!t.which)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),d=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),function(){function t(e,t,i){return[parseFloat(e[0])*(p.test(e[0])?t/100:1),parseFloat(e[1])*(p.test(e[1])?i/100:1)]}function i(t,i){return parseInt(e.css(t,i),10)||0}function s(t){var i=t[0];return 9===i.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(i)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,u=/top|center|bottom/,d=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,p=/%$/,f=e.fn.position;e.position={scrollbarWidth:function(){if(void 0!==n)return n;var t,i,s=e("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),a=s.children()[0];return e("body").append(s),t=a.offsetWidth,s.css("overflow","scroll"),i=a.offsetWidth,t===i&&(i=s[0].clientWidth),s.remove(),n=t-i},getScrollInfo:function(t){var i=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),s=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),n="scroll"===i||"auto"===i&&t.width<t.element[0].scrollWidth,a="scroll"===s||"auto"===s&&t.height<t.element[0].scrollHeight;return{width:a?e.position.scrollbarWidth():0,height:n?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var i=e(t||window),s=e.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType;return{element:i,isWindow:s,isDocument:n,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s||n?i.width():i.outerWidth(),height:s||n?i.height():i.outerHeight()}}},e.fn.position=function(n){if(!n||!n.of)return f.apply(this,arguments);n=e.extend({},n);var p,m,g,v,y,b,_=e(n.of),x=e.position.getWithinInfo(n.within),w=e.position.getScrollInfo(x),k=(n.collision||"flip").split(" "),T={};return b=s(_),_[0].preventDefault&&(n.at="left top"),m=b.width,g=b.height,v=b.offset,y=e.extend({},v),e.each(["my","at"],function(){var e,t,i=(n[this]||"").split(" ");1===i.length&&(i=l.test(i[0])?i.concat(["center"]):u.test(i[0])?["center"].concat(i):["center","center"]),i[0]=l.test(i[0])?i[0]:"center",i[1]=u.test(i[1])?i[1]:"center",e=d.exec(i[0]),t=d.exec(i[1]),T[this]=[e?e[0]:0,t?t[0]:0],n[this]=[c.exec(i[0])[0],c.exec(i[1])[0]]}),1===k.length&&(k[1]=k[0]),"right"===n.at[0]?y.left+=m:"center"===n.at[0]&&(y.left+=m/2),"bottom"===n.at[1]?y.top+=g:"center"===n.at[1]&&(y.top+=g/2),p=t(T.at,m,g),y.left+=p[0],y.top+=p[1],this.each(function(){var s,l,u=e(this),d=u.outerWidth(),c=u.outerHeight(),f=i(this,"marginLeft"),b=i(this,"marginTop"),D=d+f+i(this,"marginRight")+w.width,S=c+b+i(this,"marginBottom")+w.height,M=e.extend({},y),C=t(T.my,u.outerWidth(),u.outerHeight());"right"===n.my[0]?M.left-=d:"center"===n.my[0]&&(M.left-=d/2),"bottom"===n.my[1]?M.top-=c:"center"===n.my[1]&&(M.top-=c/2),M.left+=C[0],M.top+=C[1],a||(M.left=h(M.left),M.top=h(M.top)),s={marginLeft:f,marginTop:b},e.each(["left","top"],function(t,i){e.ui.position[k[t]]&&e.ui.position[k[t]][i](M,{targetWidth:m,targetHeight:g,elemWidth:d,elemHeight:c,collisionPosition:s,collisionWidth:D,collisionHeight:S,offset:[p[0]+C[0],p[1]+C[1]],my:n.my,at:n.at,within:x,elem:u})}),n.using&&(l=function(e){var t=v.left-M.left,i=t+m-d,s=v.top-M.top,a=s+g-c,h={target:{element:_,left:v.left,top:v.top,width:m,height:g},element:{element:u,left:M.left,top:M.top,width:d,height:c},horizontal:0>i?"left":t>0?"right":"center",vertical:0>a?"top":s>0?"bottom":"middle"};d>m&&m>r(t+i)&&(h.horizontal="center"),c>g&&g>r(s+a)&&(h.vertical="middle"),h.important=o(r(t),r(i))>o(r(s),r(a))?"horizontal":"vertical",n.using.call(this,e,h)}),u.offset(e.extend(M,{using:l}))})},e.ui.position={fit:{left:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=e.left-t.collisionPosition.marginLeft,h=n-r,l=r+t.collisionWidth-a-n;t.collisionWidth>a?h>0&&0>=l?(i=e.left+h+t.collisionWidth-a-n,e.left+=h-i):e.left=l>0&&0>=h?n:h>l?n+a-t.collisionWidth:n:h>0?e.left+=h:l>0?e.left-=l:e.left=o(e.left-r,e.left)},top:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollTop:s.offset.top,a=t.within.height,r=e.top-t.collisionPosition.marginTop,h=n-r,l=r+t.collisionHeight-a-n;t.collisionHeight>a?h>0&&0>=l?(i=e.top+h+t.collisionHeight-a-n,e.top+=h-i):e.top=l>0&&0>=h?n:h>l?n+a-t.collisionHeight:n:h>0?e.top+=h:l>0?e.top-=l:e.top=o(e.top-r,e.top)}},flip:{left:function(e,t){var i,s,n=t.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=e.left-t.collisionPosition.marginLeft,u=l-h,d=l+t.collisionWidth-o-h,c="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,p="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,f=-2*t.offset[0];0>u?(i=e.left+c+p+f+t.collisionWidth-o-a,(0>i||r(u)>i)&&(e.left+=c+p+f)):d>0&&(s=e.left-t.collisionPosition.marginLeft+c+p+f-h,(s>0||d>r(s))&&(e.left+=c+p+f))},top:function(e,t){var i,s,n=t.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=e.top-t.collisionPosition.marginTop,u=l-h,d=l+t.collisionHeight-o-h,c="top"===t.my[1],p=c?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,f="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,m=-2*t.offset[1];0>u?(s=e.top+p+f+m+t.collisionHeight-o-a,(0>s||r(u)>s)&&(e.top+=p+f+m)):d>0&&(i=e.top-t.collisionPosition.marginTop+p+f+m-h,(i>0||d>r(i))&&(e.top+=p+f+m))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,i,s,n,o,r=document.getElementsByTagName("body")[0],h=document.createElement("div");t=document.createElement(r?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},r&&e.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(o in s)t.style[o]=s[o];t.appendChild(h),i=r||document.documentElement,i.insertBefore(t,i.firstChild),h.style.cssText="position: absolute; left: 10.7432222px;",n=e(h).offset().left,a=n>10&&11>n,t.innerHTML="",i.removeChild(t)}()}(),e.ui.position,e.widget("ui.accordion",{version:"1.11.4",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").removeUniqueId(),this._destroyIcons(),e=this.headers.next().removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&(this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)),void 0)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,s=this.headers.length,n=this.headers.index(t.target),a=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:a=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:a=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:a=this.headers[0];break;case i.END:a=this.headers[s-1]}a&&(e(t.target).attr("tabIndex",-1),e(a).attr("tabIndex",0),a.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var e=this.headers,t=this.panels;this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-state-default ui-corner-all"),this.panels=this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide(),t&&(this._off(e.not(this.headers)),this._off(t.not(this.panels)))},_refresh:function(){var t,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(){var t=e(this),i=t.uniqueId().attr("id"),s=t.next(),n=s.uniqueId().attr("id");t.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(t=n.height(),this.element.siblings(":visible").each(function(){var i=e(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(t-=i.outerHeight(!0))}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===s&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n[0]===s[0],o=a&&i.collapsible,r=o?e():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:o?e():n,newPanel:r};t.preventDefault(),a&&!i.collapsible||this._trigger("beforeActivate",t,l)===!1||(i.active=o?!1:this.headers.index(n),this.active=a?e():n,this._toggle(l),s.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),a||(n.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&n.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var i=t.newPanel,s=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,t):(s.hide(),i.show(),this._toggleComplete(t)),s.attr({"aria-hidden":"true"}),s.prev().attr({"aria-selected":"false","aria-expanded":"false"}),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===parseInt(e(this).attr("tabIndex"),10)}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(e,t,i){var s,n,a,o=this,r=0,h=e.css("box-sizing"),l=e.length&&(!t.length||e.index()<t.index()),u=this.options.animate||{},d=l&&u.down||u,c=function(){o._toggleComplete(i)};return"number"==typeof d&&(a=d),"string"==typeof d&&(n=d),n=n||d.easing||u.easing,a=a||d.duration||u.duration,t.length?e.length?(s=e.show().outerHeight(),t.animate(this.hideProps,{duration:a,easing:n,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(this.showProps,{duration:a,easing:n,complete:c,step:function(e,i){i.now=Math.round(e),"height"!==i.prop?"content-box"===h&&(r+=i.now):"content"!==o.options.heightStyle&&(i.now=Math.round(s-t.outerHeight()-r),r=0)}}),void 0):t.animate(this.hideProps,a,n,c):e.animate(this.showProps,a,n,c)},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}}),e.widget("ui.menu",{version:"1.11.4",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},items:"> *",menus:"ul",position:{my:"left-1 top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item":function(e){e.preventDefault()},"click .ui-menu-item":function(t){var i=e(t.target);!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&e(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){if(!this.previousFilter){var i=e(t.currentTarget);
7
- i.siblings(".ui-state-active").removeClass("ui-state-active"),this.focus(t,i)}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var i=this.active||this.element.find(this.options.items).eq(0);t||this.focus(e,i)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){this._closeOnDocumentClick(e)&&this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-menu-icons ui-front").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").removeUniqueId().removeClass("ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){var i,s,n,a,o=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:o=!1,s=this.previousFilter||"",n=String.fromCharCode(t.keyCode),a=!1,clearTimeout(this.filterTimer),n===s?a=!0:n=s+n,i=this._filterMenuItems(n),i=a&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(t.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(t,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}o&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.is("[aria-haspopup='true']")?this.expand(e):this.select(e))},refresh:function(){var t,i,s=this,n=this.options.icons.submenu,a=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),a.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-front").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),i=t.parent(),s=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);i.attr("aria-haspopup","true").prepend(s),t.attr("aria-labelledby",i.attr("id"))}),t=a.add(this.element),i=t.find(this.options.items),i.not(".ui-menu-item").each(function(){var t=e(this);s._isDivider(t)&&t.addClass("ui-widget-content ui-menu-divider")}),i.not(".ui-menu-item, .ui-menu-divider").addClass("ui-menu-item").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){"icons"===e&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},focus:function(e,t){var i,s;this.blur(e,e&&"focus"===e.type),this._scrollIntoView(t),this.active=t.first(),s=this.active.addClass("ui-state-focus").removeClass("ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").addClass("ui-state-active"),e&&"keydown"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=t.children(".ui-menu"),i.length&&e&&/^mouse/.test(e.type)&&this._startOpening(i),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,n=t.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=t.outerHeight(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),"true"===e.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var i=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(t,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(t),this.activeMenu=s},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find(".ui-state-active").not(".ui-state-focus").removeClass("ui-state-active")},_closeOnDocumentClick:function(t){return!e(t.target).closest(".ui-menu").length},_isDivider:function(e){return!/[^\-\u2014\u2013\s]/.test(e.text())},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,i){var s;this.active&&(s="first"===e||"last"===e?this.active["first"===e?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[e+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[t]()),this.focus(i,s)},nextPage:function(t){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=e(this),0>i.offset().top-s-n}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(t),void 0)},previousPage:function(t){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=e(this),i.offset().top-s+n>0}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items).first())),void 0):(this.next(t),void 0)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,i)},_filterMenuItems:function(t){var i=t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&"),s=RegExp("^"+i,"i");return this.activeMenu.find(this.options.items).filter(".ui-menu-item").filter(function(){return s.test(e.trim(e(this).text()))})}}),e.widget("ui.autocomplete",{version:"1.11.4",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,void 0;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),void 0):(this._searchTimeout(e),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(e),this._change(e),void 0)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:n})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&e.trim(s).length&&(this.liveRegion.children().hide(),e("<div>").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("<span>",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),i=this.menu.element.is(":visible"),s=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;(!t||t&&!i&&!s)&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length<this.options.minLength?this.close(t):this._trigger("search",t)!==!1?this._search(e):void 0},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var t=++this.requestIndex;return e.proxy(function(e){t===this.requestIndex&&this.__response(e),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},this)},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return"string"==typeof t?{label:t,value:t}:e.extend({},t,{label:t.label||t.value,value:t.value||t.label})})},_suggest:function(t){var i=this.menu.element.empty();this._renderMenu(i,t),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,i){var s=this;e.each(i,function(e,i){s._renderItemData(t,i)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,i){return e("<li>").text(i.label).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[e](t),void 0):(this.search(null,t),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.children().hide(),e("<div>").text(i).appendTo(this.liveRegion))}}),e.ui.autocomplete;var c,p="ui-button ui-widget ui-state-default ui-corner-all",f="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",m=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},g=function(t){var i=t.name,s=t.form,n=e([]);return i&&(i=i.replace(/'/g,"\\'"),n=s?e(s).find("[name='"+i+"'][type=radio]"):e("[name='"+i+"'][type=radio]",t.ownerDocument).filter(function(){return!this.form})),n};e.widget("ui.button",{version:"1.11.4",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,m),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,i=this.options,s="checkbox"===this.type||"radio"===this.type,n=s?"":"ui-state-active";null===i.label&&(i.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(p).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){i.disabled||this===c&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){i.disabled||e(this).removeClass(n)}).bind("click"+this.eventNamespace,function(e){i.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this._on({focus:function(){this.buttonElement.addClass("ui-state-focus")},blur:function(){this.buttonElement.removeClass("ui-state-focus")}}),s&&this.element.bind("change"+this.eventNamespace,function(){t.refresh()}),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return i.disabled?!1:void 0}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(i.disabled)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var s=t.element[0];g(s).not(s).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return i.disabled?!1:(e(this).addClass("ui-state-active"),c=this,t.document.one("mouseup",function(){c=null}),void 0)}).bind("mouseup"+this.eventNamespace,function(){return i.disabled?!1:(e(this).removeClass("ui-state-active"),void 0)}).bind("keydown"+this.eventNamespace,function(t){return i.disabled?!1:((t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active"),void 0)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",i.disabled),this._resetButton()},_determineButtonType:function(){var e,t,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(p+" ui-state-active "+f).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){return this._super(e,t),"disabled"===e?(this.widget().toggleClass("ui-state-disabled",!!t),this.element.prop("disabled",!!t),t&&("checkbox"===this.type||"radio"===this.type?this.buttonElement.removeClass("ui-state-focus"):this.buttonElement.removeClass("ui-state-focus ui-state-active")),void 0):(this._resetButton(),void 0)},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),"radio"===this.type?g(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),void 0;var t=this.buttonElement.removeClass(f),i=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),s=this.options.icons,n=s.primary&&s.secondary,a=[];s.primary||s.secondary?(this.options.text&&a.push("ui-button-text-icon"+(n?"s":s.primary?"-primary":"-secondary")),s.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+s.primary+"'></span>"),s.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+s.secondary+"'></span>"),this.options.text||(a.push(n?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(i)))):a.push("ui-button-text-only"),t.addClass(a.join(" "))}}),e.widget("ui.buttonset",{version:"1.11.4",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){"disabled"===e&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t="rtl"===this.element.css("direction"),i=this.element.find(this.options.items),s=i.filter(":ui-button");i.not(":ui-button").button(),s.button("refresh"),this.buttons=i.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}}),e.ui.button,e.extend(e.ui,{datepicker:{version:"1.11.4"}});var v;e.extend(n.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return r(this._defaults,e||{}),this},_attachDatepicker:function(t,i){var s,n,a;s=t.nodeName.toLowerCase(),n="div"===s||"span"===s,t.id||(this.uuid+=1,t.id="dp"+this.uuid),a=this._newInst(e(t),n),a.settings=e.extend({},i||{}),"input"===s?this._connectDatepicker(t,a):n&&this._inlineDatepicker(t,a)},_newInst:function(t,i){var s=t[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:s,input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?a(e("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(t,i){var s=e(t);i.append=e([]),i.trigger=e([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),e.data(t,"datepicker",i),i.settings.disabled&&this._disableDatepicker(t))},_attachments:function(t,i){var s,n,a,o=this._get(i,"appendText"),r=this._get(i,"isRTL");i.append&&i.append.remove(),o&&(i.append=e("<span class='"+this._appendClass+"'>"+o+"</span>"),t[r?"before":"after"](i.append)),t.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,"showOn"),("focus"===s||"both"===s)&&t.focus(this._showDatepicker),("button"===s||"both"===s)&&(n=this._get(i,"buttonText"),a=this._get(i,"buttonImage"),i.trigger=e(this._get(i,"buttonImageOnly")?e("<img/>").addClass(this._triggerClass).attr({src:a,alt:n,title:n}):e("<button type='button'></button>").addClass(this._triggerClass).html(a?e("<img/>").attr({src:a,alt:n,title:n}):n)),t[r?"before":"after"](i.trigger),i.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,i,s,n,a=new Date(2009,11,20),o=this._get(e,"dateFormat");o.match(/[DM]/)&&(t=function(e){for(i=0,s=0,n=0;e.length>n;n++)e[n].length>i&&(i=e[n].length,s=n);return s},a.setMonth(t(this._get(e,o.match(/MM/)?"monthNames":"monthNamesShort"))),a.setDate(t(this._get(e,o.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),e.input.attr("size",this._formatDate(e,a).length)}},_inlineDatepicker:function(t,i){var s=e(t);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),e.data(t,"datepicker",i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(t),i.dpDiv.css("display","block"))},_dialogDatepicker:function(t,i,s,n,a){var o,h,l,u,d,c=this._dialogInst;return c||(this.uuid+=1,o="dp"+this.uuid,this._dialogInput=e("<input type='text' id='"+o+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),c=this._dialogInst=this._newInst(this._dialogInput,!1),c.settings={},e.data(this._dialogInput[0],"datepicker",c)),r(c.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(c,i):i,this._dialogInput.val(i),this._pos=a?a.length?a:[a.pageX,a.pageY]:null,this._pos||(h=document.documentElement.clientWidth,l=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[h/2-100+u,l/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),c.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],"datepicker",c),this},_destroyDatepicker:function(t){var i,s=e(t),n=e.data(t,"datepicker");s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),e.removeData(t,"datepicker"),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty(),v===n&&(v=null))},_enableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,"datepicker");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,"datepicker");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,"datepicker")}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(t,i,s){var n,a,o,h,l=this._getInst(t);return 2===arguments.length&&"string"==typeof i?"defaults"===i?e.extend({},e.datepicker._defaults):l?"all"===i?e.extend({},l.settings):this._get(l,i):null:(n=i||{},"string"==typeof i&&(n={},n[i]=s),l&&(this._curInst===l&&this._hideDatepicker(),a=this._getDateDatepicker(t,!0),o=this._getMinMaxDate(l,"min"),h=this._getMinMaxDate(l,"max"),r(l.settings,n),null!==o&&void 0!==n.dateFormat&&void 0===n.minDate&&(l.settings.minDate=this._formatDate(l,o)),null!==h&&void 0!==n.dateFormat&&void 0===n.maxDate&&(l.settings.maxDate=this._formatDate(l,h)),"disabled"in n&&(n.disabled?this._disableDatepicker(t):this._enableDatepicker(t)),this._attachments(e(t),l),this._autoSize(l),this._setDate(l,a),this._updateAlternate(l),this._updateDatepicker(l)),void 0)},_changeDatepicker:function(e,t,i){this._optionDatepicker(e,t,i)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var i=this._getInst(e);i&&(this._setDate(i,t),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(e,t){var i=this._getInst(e);return i&&!i.inline&&this._setDateFromField(i,t),i?this._getDate(i):null},_doKeyDown:function(t){var i,s,n,a=e.datepicker._getInst(t.target),o=!0,r=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),o=!1;break;case 13:return n=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",a.dpDiv),n[0]&&e.datepicker._selectDay(t.target,a.selectedMonth,a.selectedYear,n[0]),i=e.datepicker._get(a,"onSelect"),i?(s=e.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,"stepBigMonths"):-e.datepicker._get(a,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,"stepBigMonths"):+e.datepicker._get(a,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),o=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),o=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?1:-1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,"stepBigMonths"):-e.datepicker._get(a,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),o=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?-1:1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,"stepBigMonths"):+e.datepicker._get(a,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),o=t.ctrlKey||t.metaKey;break;default:o=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):o=!1;o&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var i,s,n=e.datepicker._getInst(t.target);
8
- return e.datepicker._get(n,"constrainInput")?(i=e.datepicker._possibleChars(e.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==t.charCode?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||" ">s||!i||i.indexOf(s)>-1):void 0},_doKeyUp:function(t){var i,s=e.datepicker._getInst(t.target);if(s.input.val()!==s.lastVal)try{i=e.datepicker.parseDate(e.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,e.datepicker._getFormatConfig(s)),i&&(e.datepicker._setDateFromField(s),e.datepicker._updateAlternate(s),e.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,n,a,o,h,l,u;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),n=e.datepicker._get(i,"beforeShow"),a=n?n.apply(t,[t,i]):{},a!==!1&&(r(i.settings,a),i.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(i),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),o=!1,e(t).parents().each(function(){return o|="fixed"===e(this).css("position"),!o}),h={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(i),h=e.datepicker._checkOffset(i,h,o),i.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":o?"fixed":"absolute",display:"none",left:h.left+"px",top:h.top+"px"}),i.inline||(l=e.datepicker._get(i,"showAnim"),u=e.datepicker._get(i,"duration"),i.dpDiv.css("z-index",s(e(t))+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[l]?i.dpDiv.show(l,e.datepicker._get(i,"showOptions"),u):i.dpDiv[l||"show"](l?u:null),e.datepicker._shouldFocusInput(i)&&i.input.focus(),e.datepicker._curInst=i))}},_updateDatepicker:function(t){this.maxRows=4,v=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t);var i,s=this._getNumberOfMonths(t),n=s[1],a=17,r=t.dpDiv.find("."+this._dayOverClass+" a");r.length>0&&o.apply(r.get(0)),t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&t.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",a*n+"em"),t.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(i=t.yearshtml,setTimeout(function(){i===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),i=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&!e.input.is(":focus")},_checkOffset:function(t,i,s){var n=t.dpDiv.outerWidth(),a=t.dpDiv.outerHeight(),o=t.input?t.input.outerWidth():0,r=t.input?t.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:e(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:e(document).scrollTop());return i.left-=this._get(t,"isRTL")?n-o:0,i.left-=s&&i.left===t.input.offset().left?e(document).scrollLeft():0,i.top-=s&&i.top===t.input.offset().top+r?e(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+r):0),i},_findPos:function(t){for(var i,s=this._getInst(t),n=this._get(s,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[n?"previousSibling":"nextSibling"];return i=e(t).offset(),[i.left,i.top]},_hideDatepicker:function(t){var i,s,n,a,o=this._curInst;!o||t&&o!==e.data(t,"datepicker")||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){e.datepicker._tidyDialog(o)},e.effects&&(e.effects.effect[i]||e.effects[i])?o.dpDiv.hide(i,e.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(e.datepicker._curInst){var i=e(t.target),s=e.datepicker._getInst(i[0]);(i[0].id!==e.datepicker._mainDivId&&0===i.parents("#"+e.datepicker._mainDivId).length&&!i.hasClass(e.datepicker.markerClassName)&&!i.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||i.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==s)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,i,s){var n=e(t),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(t){var i,s=e(t),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(t,i,s){var n=e(t),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(t,i,s,n){var a,o=e(t);e(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(o[0])||(a=this._getInst(o[0]),a.selectedDay=a.currentDay=e("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(t,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(t){var i=e(t);this._selectDate(i,"")},_selectDate:function(t,i){var s,n=e(t),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.input&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var i,s,n,a=this._get(t,"altField");a&&(i=this._get(t,"altFormat")||this._get(t,"dateFormat"),s=this._getDate(t),n=this.formatDate(i,s,this._getFormatConfig(t)),e(a).each(function(){e(this).val(n)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,""]},iso8601Week:function(e){var t,i=new Date(e.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),t=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((t-i)/864e5)/7)+1},parseDate:function(t,i,s){if(null==t||null==i)throw"Invalid arguments";if(i="object"==typeof i?""+i:i+"",""===i)return null;var n,a,o,r,h=0,l=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=typeof l?l:(new Date).getFullYear()%100+parseInt(l,10),d=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,c=(s?s.dayNames:null)||this._defaults.dayNames,p=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,f=(s?s.monthNames:null)||this._defaults.monthNames,m=-1,g=-1,v=-1,y=-1,b=!1,_=function(e){var i=t.length>n+1&&t.charAt(n+1)===e;return i&&n++,i},x=function(e){var t=_(e),s="@"===e?14:"!"===e?20:"y"===e&&t?4:"o"===e?3:2,n="y"===e?s:1,a=RegExp("^\\d{"+n+","+s+"}"),o=i.substring(h).match(a);if(!o)throw"Missing number at position "+h;return h+=o[0].length,parseInt(o[0],10)},w=function(t,s,n){var a=-1,o=e.map(_(t)?n:s,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(o,function(e,t){var s=t[1];return i.substr(h,s.length).toLowerCase()===s.toLowerCase()?(a=t[0],h+=s.length,!1):void 0}),-1!==a)return a+1;throw"Unknown name at position "+h},k=function(){if(i.charAt(h)!==t.charAt(n))throw"Unexpected literal at position "+h;h++};for(n=0;t.length>n;n++)if(b)"'"!==t.charAt(n)||_("'")?k():b=!1;else switch(t.charAt(n)){case"d":v=x("d");break;case"D":w("D",d,c);break;case"o":y=x("o");break;case"m":g=x("m");break;case"M":g=w("M",p,f);break;case"y":m=x("y");break;case"@":r=new Date(x("@")),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case"!":r=new Date((x("!")-this._ticksTo1970)/1e4),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case"'":_("'")?k():b=!0;break;default:k()}if(i.length>h&&(o=i.substr(h),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===m?m=(new Date).getFullYear():100>m&&(m+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=m?0:-100)),y>-1)for(g=1,v=y;;){if(a=this._getDaysInMonth(m,g-1),a>=v)break;g++,v-=a}if(r=this._daylightSavingAdjust(new Date(m,g-1,v)),r.getFullYear()!==m||r.getMonth()+1!==g||r.getDate()!==v)throw"Invalid date";return r},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,i){if(!t)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,o=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,r=(i?i.monthNames:null)||this._defaults.monthNames,h=function(t){var i=e.length>s+1&&e.charAt(s+1)===t;return i&&s++,i},l=function(e,t,i){var s=""+t;if(h(e))for(;i>s.length;)s="0"+s;return s},u=function(e,t,i,s){return h(e)?s[t]:i[t]},d="",c=!1;if(t)for(s=0;e.length>s;s++)if(c)"'"!==e.charAt(s)||h("'")?d+=e.charAt(s):c=!1;else switch(e.charAt(s)){case"d":d+=l("d",t.getDate(),2);break;case"D":d+=u("D",t.getDay(),n,a);break;case"o":d+=l("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":d+=l("m",t.getMonth()+1,2);break;case"M":d+=u("M",t.getMonth(),o,r);break;case"y":d+=h("y")?t.getFullYear():(10>t.getYear()%100?"0":"")+t.getYear()%100;break;case"@":d+=t.getTime();break;case"!":d+=1e4*t.getTime()+this._ticksTo1970;break;case"'":h("'")?d+="'":c=!0;break;default:d+=e.charAt(s)}return d},_possibleChars:function(e){var t,i="",s=!1,n=function(i){var s=e.length>t+1&&e.charAt(t+1)===i;return s&&t++,s};for(t=0;e.length>t;t++)if(s)"'"!==e.charAt(t)||n("'")?i+=e.charAt(t):s=!1;else switch(e.charAt(t)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=e.charAt(t)}return i},_get:function(e,t){return void 0!==e.settings[t]?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var i=this._get(e,"dateFormat"),s=e.lastVal=e.input?e.input.val():null,n=this._getDefaultDate(e),a=n,o=this._getFormatConfig(e);try{a=this.parseDate(i,s,o)||n}catch(r){s=t?"":s}e.selectedDay=a.getDate(),e.drawMonth=e.selectedMonth=a.getMonth(),e.drawYear=e.selectedYear=a.getFullYear(),e.currentDay=s?a.getDate():0,e.currentMonth=s?a.getMonth():0,e.currentYear=s?a.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,i,s){var n=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},a=function(i){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),i,e.datepicker._getFormatConfig(t))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,a=n.getFullYear(),o=n.getMonth(),r=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":r+=parseInt(l[1],10);break;case"w":case"W":r+=7*parseInt(l[1],10);break;case"m":case"M":o+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o));break;case"y":case"Y":a+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o))}l=h.exec(i)}return new Date(a,o,r)},o=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return o=o&&"Invalid Date"==""+o?s:o,o&&(o.setHours(0),o.setMinutes(0),o.setSeconds(0),o.setMilliseconds(0)),this._daylightSavingAdjust(o)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,i){var s=!t,n=e.selectedMonth,a=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),n===e.selectedMonth&&a===e.selectedYear||i||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(s?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&""===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var i=this._get(t,"stepMonths"),s="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){e.datepicker._adjustDate(s,-i,"M")},next:function(){e.datepicker._adjustDate(s,+i,"M")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(s)},selectDay:function(){return e.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return e.datepicker._selectMonthYear(s,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,i,s,n,a,o,r,h,l,u,d,c,p,f,m,g,v,y,b,_,x,w,k,T,D,S,M,C,N,A,P,I,H,z,F,E,O,j,W,L=new Date,R=this._daylightSavingAdjust(new Date(L.getFullYear(),L.getMonth(),L.getDate())),Y=this._get(e,"isRTL"),B=this._get(e,"showButtonPanel"),J=this._get(e,"hideIfNoPrevNext"),q=this._get(e,"navigationAsDateFormat"),K=this._getNumberOfMonths(e),V=this._get(e,"showCurrentAtPos"),U=this._get(e,"stepMonths"),Q=1!==K[0]||1!==K[1],G=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),X=this._getMinMaxDate(e,"min"),$=this._getMinMaxDate(e,"max"),Z=e.drawMonth-V,et=e.drawYear;if(0>Z&&(Z+=12,et--),$)for(t=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-K[0]*K[1]+1,$.getDate())),t=X&&X>t?X:t;this._daylightSavingAdjust(new Date(et,Z,1))>t;)Z--,0>Z&&(Z=11,et--);for(e.drawMonth=Z,e.drawYear=et,i=this._get(e,"prevText"),i=q?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z-U,1)),this._getFormatConfig(e)):i,s=this._canAdjustMonth(e,-1,et,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>":J?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>",n=this._get(e,"nextText"),n=q?this.formatDate(n,this._daylightSavingAdjust(new Date(et,Z+U,1)),this._getFormatConfig(e)):n,a=this._canAdjustMonth(e,1,et,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>":J?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>",o=this._get(e,"currentText"),r=this._get(e,"gotoCurrent")&&e.currentDay?G:R,o=q?this.formatDate(o,r,this._getFormatConfig(e)):o,h=e.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(e,"closeText")+"</button>",l=B?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(Y?h:"")+(this._isInRange(e,r)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+o+"</button>":"")+(Y?"":h)+"</div>":"",u=parseInt(this._get(e,"firstDay"),10),u=isNaN(u)?0:u,d=this._get(e,"showWeek"),c=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),f=this._get(e,"monthNames"),m=this._get(e,"monthNamesShort"),g=this._get(e,"beforeShowDay"),v=this._get(e,"showOtherMonths"),y=this._get(e,"selectOtherMonths"),b=this._getDefaultDate(e),_="",w=0;K[0]>w;w++){for(k="",this.maxRows=4,T=0;K[1]>T;T++){if(D=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),S=" ui-corner-all",M="",Q){if(M+="<div class='ui-datepicker-group",K[1]>1)switch(T){case 0:M+=" ui-datepicker-group-first",S=" ui-corner-"+(Y?"right":"left");break;case K[1]-1:M+=" ui-datepicker-group-last",S=" ui-corner-"+(Y?"left":"right");break;default:M+=" ui-datepicker-group-middle",S=""}M+="'>"}for(M+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+S+"'>"+(/all|left/.test(S)&&0===w?Y?a:s:"")+(/all|right/.test(S)&&0===w?Y?s:a:"")+this._generateMonthYearHeader(e,Z,et,X,$,w>0||T>0,f,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",C=d?"<th class='ui-datepicker-week-col'>"+this._get(e,"weekHeader")+"</th>":"",x=0;7>x;x++)N=(x+u)%7,C+="<th scope='col'"+((x+u+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+c[N]+"'>"+p[N]+"</span></th>";for(M+=C+"</tr></thead><tbody>",A=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,A)),P=(this._getFirstDayOfMonth(et,Z)-u+7)%7,I=Math.ceil((P+A)/7),H=Q?this.maxRows>I?this.maxRows:I:I,this.maxRows=H,z=this._daylightSavingAdjust(new Date(et,Z,1-P)),F=0;H>F;F++){for(M+="<tr>",E=d?"<td class='ui-datepicker-week-col'>"+this._get(e,"calculateWeek")(z)+"</td>":"",x=0;7>x;x++)O=g?g.apply(e.input?e.input[0]:null,[z]):[!0,""],j=z.getMonth()!==Z,W=j&&!y||!O[0]||X&&X>z||$&&z>$,E+="<td class='"+((x+u+6)%7>=5?" ui-datepicker-week-end":"")+(j?" ui-datepicker-other-month":"")+(z.getTime()===D.getTime()&&Z===e.selectedMonth&&e._keyEvent||b.getTime()===z.getTime()&&b.getTime()===D.getTime()?" "+this._dayOverClass:"")+(W?" "+this._unselectableClass+" ui-state-disabled":"")+(j&&!v?"":" "+O[1]+(z.getTime()===G.getTime()?" "+this._currentClass:"")+(z.getTime()===R.getTime()?" ui-datepicker-today":""))+"'"+(j&&!v||!O[2]?"":" title='"+O[2].replace(/'/g,"&#39;")+"'")+(W?"":" data-handler='selectDay' data-event='click' data-month='"+z.getMonth()+"' data-year='"+z.getFullYear()+"'")+">"+(j&&!v?"&#xa0;":W?"<span class='ui-state-default'>"+z.getDate()+"</span>":"<a class='ui-state-default"+(z.getTime()===R.getTime()?" ui-state-highlight":"")+(z.getTime()===G.getTime()?" ui-state-active":"")+(j?" ui-priority-secondary":"")+"' href='#'>"+z.getDate()+"</a>")+"</td>",z.setDate(z.getDate()+1),z=this._daylightSavingAdjust(z);M+=E+"</tr>"}Z++,Z>11&&(Z=0,et++),M+="</tbody></table>"+(Q?"</div>"+(K[0]>0&&T===K[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),k+=M}_+=k}return _+=l,e._keyEvent=!1,_},_generateMonthYearHeader:function(e,t,i,s,n,a,o,r){var h,l,u,d,c,p,f,m,g=this._get(e,"changeMonth"),v=this._get(e,"changeYear"),y=this._get(e,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",_="";if(a||!g)_+="<span class='ui-datepicker-month'>"+o[t]+"</span>";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,_+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",u=0;12>u;u++)(!h||u>=s.getMonth())&&(!l||n.getMonth()>=u)&&(_+="<option value='"+u+"'"+(u===t?" selected='selected'":"")+">"+r[u]+"</option>");_+="</select>"}if(y||(b+=_+(!a&&g&&v?"":"&#xa0;")),!e.yearshtml)if(e.yearshtml="",a||!v)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(d=this._get(e,"yearRange").split(":"),c=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?i+parseInt(e.substring(1),10):e.match(/[+\-].*/)?c+parseInt(e,10):parseInt(e,10);return isNaN(t)?c:t},f=p(d[0]),m=Math.max(f,p(d[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,e.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=f;f++)e.yearshtml+="<option value='"+f+"'"+(f===i?" selected='selected'":"")+">"+f+"</option>";e.yearshtml+="</select>",b+=e.yearshtml,e.yearshtml=null}return b+=this._get(e,"yearSuffix"),y&&(b+=(!a&&g&&v?"":"&#xa0;")+_),b+="</div>"},_adjustInstDate:function(e,t,i){var s=e.drawYear+("Y"===i?t:0),n=e.drawMonth+("M"===i?t:0),a=Math.min(e.selectedDay,this._getDaysInMonth(s,n))+("D"===i?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(s,n,a)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var i=this._getMinMaxDate(e,"min"),s=this._getMinMaxDate(e,"max"),n=i&&i>t?i:t;return s&&n>s?s:n},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,i,s){var n=this._getNumberOfMonths(e),a=this._daylightSavingAdjust(new Date(i,s+(0>t?t:n[0]*n[1]),1));return 0>t&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(e,a)},_isInRange:function(e,t){var i,s,n=this._getMinMaxDate(e,"min"),a=this._getMinMaxDate(e,"max"),o=null,r=null,h=this._get(e,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),o=parseInt(i[0],10),r=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(o+=s),i[1].match(/[+\-].*/)&&(r+=s)),(!n||t.getTime()>=n.getTime())&&(!a||t.getTime()<=a.getTime())&&(!o||t.getFullYear()>=o)&&(!r||r>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t="string"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,i,s){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var n=t?"object"==typeof t?t:this._daylightSavingAdjust(new Date(s,i,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),n,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e("#"+e.datepicker._mainDivId).length&&e("body").append(e.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof t||"isDisabled"!==t&&"getDate"!==t&&"widget"!==t?"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof t?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(i)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i))},e.datepicker=new n,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.11.4",e.datepicker,e.widget("ui.draggable",e.ui.mouse,{version:"1.11.4",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),"handle"===e&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var i=this.options;return this._blurActiveElement(t),this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=e(this);return e("<div>").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var i=this.document[0];if(this.handleElement.is(t.target))try{i.activeElement&&"body"!==i.activeElement.nodeName.toLowerCase()&&e(i.activeElement).blur()}catch(s){}},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===e(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._normalizeRightBottom(),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(e){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:e.pageX-this.offset.left,top:e.pageY-this.offset.top}},_mouseDrag:function(t,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this.handleElement.addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.handleElement.removeClass("ui-draggable-handle")},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper),n=s?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options,a=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,e(a).width()-this.helperProportions.width-this.margins.left,(e(a).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)
9
- },_convertPositionTo:function(e,t){t||(t=this.position);var i="absolute"===e?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:t.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(e,t){var i,s,n,a,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),e.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),e.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a),"y"===o.axis&&(h=this.originalPageX),"x"===o.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i,s){var n=e.extend({},i,{item:s.element});s.sortables=[],e(s.options.connectToSortable).each(function(){var i=e(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",t,n))})},stop:function(t,i,s){var n=e.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,e.each(s.sortables,function(){var e=this;e.isOver?(e.isOver=0,s.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,n))})},drag:function(t,i,s){e.each(s.sortables,function(){var n=!1,a=this;a.positionAbs=s.positionAbs,a.helperProportions=s.helperProportions,a.offset.click=s.offset.click,a._intersectsWith(a.containerCache)&&(n=!0,e.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==a&&this._intersectsWith(this.containerCache)&&e.contains(a.element[0],this.element[0])&&(n=!1),n})),n?(a.isOver||(a.isOver=1,s._parent=i.helper.parent(),a.currentItem=i.helper.appendTo(a.element).data("ui-sortable-item",!0),a.options._helper=a.options.helper,a.options.helper=function(){return i.helper[0]},t.target=a.currentItem[0],a._mouseCapture(t,!0),a._mouseStart(t,!0,!0),a.offset.click.top=s.offset.click.top,a.offset.click.left=s.offset.click.left,a.offset.parent.left-=s.offset.parent.left-a.offset.parent.left,a.offset.parent.top-=s.offset.parent.top-a.offset.parent.top,s._trigger("toSortable",t),s.dropped=a.element,e.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,a.fromOutside=s),a.currentItem&&(a._mouseDrag(t),i.position=a.position)):a.isOver&&(a.isOver=0,a.cancelHelperRemoval=!0,a.options._revert=a.options.revert,a.options.revert=!1,a._trigger("out",t,a._uiHash(a)),a._mouseStop(t,!0),a.options.revert=a.options._revert,a.options.helper=a.options._helper,a.placeholder&&a.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(t),i.position=s._generatePosition(t,!0),s._trigger("fromSortable",t),s.dropped=!1,e.each(s.sortables,function(){this.refreshPositions()}))})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,i,s){var n=e("body"),a=s.options;n.css("cursor")&&(a._cursor=n.css("cursor")),n.css("cursor",a.cursor)},stop:function(t,i,s){var n=s.options;n._cursor&&e("body").css("cursor",n._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("opacity")&&(a._opacity=n.css("opacity")),n.css("opacity",a.opacity)},stop:function(t,i,s){var n=s.options;n._opacity&&e(i.helper).css("opacity",n._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(e,t,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,i,s){var n=s.options,a=!1,o=s.scrollParentNotHidden[0],r=s.document[0];o!==r&&"HTML"!==o.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+o.offsetHeight-t.pageY<n.scrollSensitivity?o.scrollTop=a=o.scrollTop+n.scrollSpeed:t.pageY-s.overflowOffset.top<n.scrollSensitivity&&(o.scrollTop=a=o.scrollTop-n.scrollSpeed)),n.axis&&"y"===n.axis||(s.overflowOffset.left+o.offsetWidth-t.pageX<n.scrollSensitivity?o.scrollLeft=a=o.scrollLeft+n.scrollSpeed:t.pageX-s.overflowOffset.left<n.scrollSensitivity&&(o.scrollLeft=a=o.scrollLeft-n.scrollSpeed))):(n.axis&&"x"===n.axis||(t.pageY-e(r).scrollTop()<n.scrollSensitivity?a=e(r).scrollTop(e(r).scrollTop()-n.scrollSpeed):e(window).height()-(t.pageY-e(r).scrollTop())<n.scrollSensitivity&&(a=e(r).scrollTop(e(r).scrollTop()+n.scrollSpeed))),n.axis&&"y"===n.axis||(t.pageX-e(r).scrollLeft()<n.scrollSensitivity?a=e(r).scrollLeft(e(r).scrollLeft()-n.scrollSpeed):e(window).width()-(t.pageX-e(r).scrollLeft())<n.scrollSensitivity&&(a=e(r).scrollLeft(e(r).scrollLeft()+n.scrollSpeed)))),a!==!1&&e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(s,t)}}),e.ui.plugin.add("draggable","snap",{start:function(t,i,s){var n=s.options;s.snapElements=[],e(n.snap.constructor!==String?n.snap.items||":data(ui-draggable)":n.snap).each(function(){var t=e(this),i=t.offset();this!==s.element[0]&&s.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:i.top,left:i.left})})},drag:function(t,i,s){var n,a,o,r,h,l,u,d,c,p,f=s.options,m=f.snapTolerance,g=i.offset.left,v=g+s.helperProportions.width,y=i.offset.top,b=y+s.helperProportions.height;for(c=s.snapElements.length-1;c>=0;c--)h=s.snapElements[c].left-s.margins.left,l=h+s.snapElements[c].width,u=s.snapElements[c].top-s.margins.top,d=u+s.snapElements[c].height,h-m>v||g>l+m||u-m>b||y>d+m||!e.contains(s.snapElements[c].item.ownerDocument,s.snapElements[c].item)?(s.snapElements[c].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(n=m>=Math.abs(u-b),a=m>=Math.abs(d-y),o=m>=Math.abs(h-v),r=m>=Math.abs(l-g),n&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||a||o||r,"outer"!==f.snapMode&&(n=m>=Math.abs(u-y),a=m>=Math.abs(d-b),o=m>=Math.abs(h-g),r=m>=Math.abs(l-v),n&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d-s.helperProportions.height,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[c].snapping&&(n||a||o||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=n||a||o||r||p)}}),e.ui.plugin.add("draggable","stack",{start:function(t,i,s){var n,a=s.options,o=e.makeArray(e(a.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});o.length&&(n=parseInt(e(o[0]).css("zIndex"),10)||0,e(o).each(function(t){e(this).css("zIndex",n+t)}),this.css("zIndex",n+o.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("zIndex")&&(a._zIndex=n.css("zIndex")),n.css("zIndex",a.zIndex)},stop:function(t,i,s){var n=s.options;n._zIndex&&e(i.helper).css("zIndex",n._zIndex)}}),e.ui.draggable,e.widget("ui.resizable",e.ui.mouse,{version:"1.11.4",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(e){return parseInt(e,10)||0},_isNumber:function(e){return!isNaN(parseInt(e,10))},_hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return t[s]>0?!0:(t[s]=1,n=t[s]>0,t[s]=0,n)},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=e(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=e(this.handles[i]),this._on(this.handles[i],{mousedown:o._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var i,s,n,a=this.options,o=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),a.containment&&(i+=e(a.containment).scrollLeft()||0,s+=e(a.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:o.width(),height:o.height()},this.originalSize=this._helper?{width:o.outerWidth(),height:o.outerHeight()}:{width:o.width(),height:o.height()},this.sizeDiff={width:o.outerWidth()-o.width(),height:o.outerHeight()-o.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof a.aspectRatio?a.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===n?this.axis+"-resize":n),o.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var i,s,n=this.originalMousePosition,a=this.axis,o=t.pageX-n.left||0,r=t.pageY-n.top||0,h=this._change[a];return this._updatePrevProperties(),h?(i=h.apply(this,[t,o,r]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var e={};return this.position.top!==this.prevPosition.top&&(e.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(e.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(e.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(e.height=this.size.height+"px"),this.helper.css(e),e},_updateVirtualBoundaries:function(e){var t,i,s,n,a,o=this.options;a={minWidth:this._isNumber(o.minWidth)?o.minWidth:0,maxWidth:this._isNumber(o.maxWidth)?o.maxWidth:1/0,minHeight:this._isNumber(o.minHeight)?o.minHeight:0,maxHeight:this._isNumber(o.maxHeight)?o.maxHeight:1/0},(this._aspectRatio||e)&&(t=a.minHeight*this.aspectRatio,s=a.minWidth/this.aspectRatio,i=a.maxHeight*this.aspectRatio,n=a.maxWidth/this.aspectRatio,t>a.minWidth&&(a.minWidth=t),s>a.minHeight&&(a.minHeight=s),a.maxWidth>i&&(a.maxWidth=i),a.maxHeight>n&&(a.maxHeight=n)),this._vBoundaries=a},_updateCache:function(e){this.offset=this.helper.offset(),this._isNumber(e.left)&&(this.position.left=e.left),this._isNumber(e.top)&&(this.position.top=e.top),this._isNumber(e.height)&&(this.size.height=e.height),this._isNumber(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,i=this.size,s=this.axis;return this._isNumber(e.height)?e.width=e.height*this.aspectRatio:this._isNumber(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===s&&(e.left=t.left+(i.width-e.width),e.top=null),"nw"===s&&(e.top=t.top+(i.height-e.height),e.left=t.left+(i.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,i=this.axis,s=this._isNumber(e.width)&&t.maxWidth&&t.maxWidth<e.width,n=this._isNumber(e.height)&&t.maxHeight&&t.maxHeight<e.height,a=this._isNumber(e.width)&&t.minWidth&&t.minWidth>e.width,o=this._isNumber(e.height)&&t.minHeight&&t.minHeight>e.height,r=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,l=/sw|nw|w/.test(i),u=/nw|ne|n/.test(i);return a&&(e.width=t.minWidth),o&&(e.height=t.minHeight),s&&(e.width=t.maxWidth),n&&(e.height=t.maxHeight),a&&l&&(e.left=r-t.minWidth),s&&l&&(e.left=r-t.maxWidth),o&&u&&(e.top=h-t.minHeight),n&&u&&(e.top=h-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_getPaddingPlusBorderDimensions:function(e){for(var t=0,i=[],s=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],n=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];4>t;t++)i[t]=parseInt(s[t],10)||0,i[t]+=parseInt(n[t],10)||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var e,t=0,i=this.helper||this.element;this._proportionallyResizeElements.length>t;t++)e=this._proportionallyResizeElements[t],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(e)),e.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,i,s,n,a,o,r,h=e(this).resizable("instance"),l=h.options,u=h.element,d=l.containment,c=d instanceof e?d.get(0):/parent/.test(d)?u.parent().get(0):d;c&&(h.containerElement=e(c),/document/.test(d)||d===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(c),i=[],e(["Top","Right","Left","Bottom"]).each(function(e,s){i[e]=h._num(t.css("padding"+s))}),h.containerOffset=t.offset(),h.containerPosition=t.position(),h.containerSize={height:t.innerHeight()-i[3],width:t.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,a=h.containerSize.width,o=h._hasScroll(c,"left")?c.scrollWidth:a,r=h._hasScroll(c)?c.scrollHeight:n,h.parentData={element:c,left:s.left,top:s.top,width:o,height:r}))},resize:function(t){var i,s,n,a,o=e(this).resizable("instance"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,d={top:0,left:0},c=o.containerElement,p=!0;c[0]!==document&&/static/.test(c.css("position"))&&(d=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-d.left),u&&(o.size.height=o.size.width/o.aspectRatio,p=!1),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio,p=!1),o.position.top=o._helper?h.top:0),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a?(o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top):(o.offset.left=o.element.offset().left,o.offset.top=o.element.offset().top),i=Math.abs(o.sizeDiff.width+(o._helper?o.offset.left-d.left:o.offset.left-h.left)),s=Math.abs(o.sizeDiff.height+(o._helper?o.offset.top-d.top:o.offset.top-h.top)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio,p=!1)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio,p=!1)),p||(o.position.left=o.prevPosition.left,o.position.top=o.prevPosition.top,o.size.width=o.prevSize.width,o.size.height=o.prevSize.height)},stop:function(){var t=e(this).resizable("instance"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).resizable("instance"),i=t.options;e(i.alsoResize).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})},resize:function(t,i){var s=e(this).resizable("instance"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0};e(n.alsoResize).each(function(){var t=e(this),s=e(this).data("ui-resizable-alsoresize"),n={},a=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(a,function(e,t){var i=(s[t]||0)+(r[t]||0);i&&i>=0&&(n[t]=i||null)}),t.css(n)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t,i=e(this).resizable("instance"),s=i.options,n=i.size,a=i.originalSize,o=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,u=h[1]||1,d=Math.round((n.width-a.width)/l)*l,c=Math.round((n.height-a.height)/u)*u,p=a.width+d,f=a.height+c,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,v=s.minWidth&&s.minWidth>p,y=s.minHeight&&s.minHeight>f;s.grid=h,v&&(p+=l),y&&(f+=u),m&&(p-=l),g&&(f-=u),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=o.top-c):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=o.left-d):((0>=f-u||0>=p-l)&&(t=i._getPaddingPlusBorderDimensions(this)),f-u>0?(i.size.height=f,i.position.top=o.top-c):(f=u-t.height,i.size.height=f,i.position.top=o.top+a.height-f),p-l>0?(i.size.width=p,i.position.left=o.left-d):(p=l-t.width,i.size.width=p,i.position.left=o.left+a.width-p))}}),e.ui.resizable,e.widget("ui.dialog",{version:"1.11.4",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"Close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._untrackInstance(),this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i,s=this;if(this._isOpen&&this._trigger("beforeClose",t)!==!1){if(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),!this.opener.filter(":focusable").focus().length)try{i=this.document[0].activeElement,i&&"body"!==i.nodeName.toLowerCase()&&e(i).blur()}catch(n){}this._hide(this.uiDialog,this.options.hide,function(){s._trigger("close",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,i){var s=!1,n=this.uiDialog.siblings(".ui-front:visible").map(function(){return+e(this).css("z-index")}).get(),a=Math.max.apply(null,n);return a>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",a+1),s=!0),s&&!i&&this._trigger("focus",t),s},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"),void 0)},_focusTabbable:function(){var e=this._focusedElement;e||(e=this.element.find("[autofocus]")),e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),void 0;
10
- if(t.keyCode===e.ui.keyCode.TAB&&!t.isDefaultPrevented()){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");t.target!==n[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==s[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){n.focus()}),t.preventDefault()):(this._delay(function(){s.focus()}),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button type='button'></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html("&#160;"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),void 0):(e.each(i,function(i,s){var n,a;s=e.isFunction(s)?{click:s,text:i}:s,s=e.extend({type:"button"},s),n=s.click,s.click=function(){n.apply(t.element[0],arguments)},a={icons:s.icons,text:s.showText},delete s.icons,delete s.showText,e("<button></button>",s).button(a).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,t(n))},drag:function(e,s){i._trigger("drag",e,t(s))},stop:function(n,a){var o=a.offset.left-i.document.scrollLeft(),r=a.offset.top-i.document.scrollTop();s.position={my:"left top",at:"left"+(o>=0?"+":"")+o+" "+"top"+(r>=0?"+":"")+r,of:i.window},e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,t(a))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,s=this.options,n=s.resizable,a=this.uiDialog.css("position"),o="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:o,start:function(s,n){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,t(n))},resize:function(e,s){i._trigger("resize",e,t(s))},stop:function(n,a){var o=i.uiDialog.offset(),r=o.left-i.document.scrollLeft(),h=o.top-i.document.scrollTop();s.height=i.uiDialog.height(),s.width=i.uiDialog.width(),s.position={my:"left top",at:"left"+(r>=0?"+":"")+r+" "+"top"+(h>=0?"+":"")+h,of:i.window},e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,t(a))}}).css("position",a)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._makeFocusTarget(),this._focusedElement=e(t.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var t=this._trackingInstances(),i=e.inArray(this,t);-1!==i&&t.splice(i,1)},_trackingInstances:function(){var e=this.document.data("ui-dialog-instances");return e||(e=[],this.document.data("ui-dialog-instances",e)),e},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,n={};e.each(t,function(e,t){i._setOption(e,t),e in i.sizeRelatedOptions&&(s=!0),e in i.resizableRelatedOptions&&(n[e]=t)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(e,t){var i,s,n=this.uiDialog;"dialogClass"===e&&n.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=n.is(":data(ui-draggable)"),i&&!t&&n.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(s=n.is(":data(ui-resizable)"),s&&!t&&n.resizable("destroy"),s&&"string"==typeof t&&n.resizable("option","handles",t),s||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),e=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),t=Math.max(0,s.minHeight-e),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-e):"none","auto"===s.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=!0;this._delay(function(){t=!1}),this.document.data("ui-dialog-overlays")||this._on(this.document,{focusin:function(e){t||this._allowInteraction(e)||(e.preventDefault(),this._trackingInstances()[0]._focusTabbable())}}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1)}},_destroyOverlay:function(){if(this.options.modal&&this.overlay){var e=this.document.data("ui-dialog-overlays")-1;e?this.document.data("ui-dialog-overlays",e):this.document.unbind("focusin").removeData("ui-dialog-overlays"),this.overlay.remove(),this.overlay=null}}}),e.widget("ui.droppable",{version:"1.11.4",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(s)?s:function(e){return e.is(s)},this.proportions=function(){return arguments.length?(t=arguments[0],void 0):t?t:t={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this.element.addClass("ui-droppable")},_addToManager:function(t){e.ui.ddmanager.droppables[t]=e.ui.ddmanager.droppables[t]||[],e.ui.ddmanager.droppables[t].push(this)},_splice:function(e){for(var t=0;e.length>t;t++)e[t]===this&&e.splice(t,1)},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];this._splice(t),this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){if("accept"===t)this.accept=e.isFunction(i)?i:function(e){return e.is(i)};else if("scope"===t){var s=e.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(t,i)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=e(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(i,{offset:i.element.offset()}),i.options.tolerance,t)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(){function e(e,t,i){return e>=t&&t+i>e}return function(t,i,s,n){if(!i.offset)return!1;var a=(t.positionAbs||t.position.absolute).left+t.margins.left,o=(t.positionAbs||t.position.absolute).top+t.margins.top,r=a+t.helperProportions.width,h=o+t.helperProportions.height,l=i.offset.left,u=i.offset.top,d=l+i.proportions().width,c=u+i.proportions().height;switch(s){case"fit":return a>=l&&d>=r&&o>=u&&c>=h;case"intersect":return a+t.helperProportions.width/2>l&&d>r-t.helperProportions.width/2&&o+t.helperProportions.height/2>u&&c>h-t.helperProportions.height/2;case"pointer":return e(n.pageY,u,i.proportions().height)&&e(n.pageX,l,i.proportions().width);case"touch":return(o>=u&&c>=o||h>=u&&c>=h||u>o&&h>c)&&(a>=l&&d>=a||r>=l&&d>=r||l>a&&r>d);default:return!1}}}(),e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue e}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance,i),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return e(this).droppable("instance").options.scope===n}),a.length&&(s=e(a[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}},e.ui.droppable;var y="ui-effects-",b=e;e.effects={effect:{}},function(e,t){function i(e,t,i){var s=d[t.type]||{};return null==e?i||!t.def?null:t.def:(e=s.floor?~~e:parseFloat(e),isNaN(e)?t.def:s.mod?(e+s.mod)%s.mod:0>e?0:e>s.max?s.max:e)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(e,a){var o,r=a.re.exec(i),h=r&&a.parse(r),l=a.space||"rgba";return h?(o=s[l](h),s[u[l].cache]=o[u[l].cache],n=s._rgba=o._rgba,!1):t}),n.length?("0,0,0,0"===n.join()&&e.extend(n,a.transparent),s):a[i]}function n(e,t,i){return i=(i+1)%1,1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+6*(t-e)*(2/3-i):e}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[2.55*e[1],2.55*e[2],2.55*e[3],e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],l=e.Color=function(t,i,s,n){return new e.Color.fn.parse(t,i,s,n)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},d={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},c=l.support={},p=e("<p>")[0],f=e.each;p.style.cssText="background-color:rgba(1,1,1,.5)",c.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),l.fn=e.extend(l.prototype,{parse:function(n,o,r,h){if(n===t)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=e(n).css(o),o=t);var d=this,c=e.type(n),p=this._rgba=[];return o!==t&&(n=[n,o,r,h],c="array"),"string"===c?this.parse(s(n)||a._default):"array"===c?(f(u.rgba.props,function(e,t){p[t.idx]=i(n[t.idx],t)}),this):"object"===c?(n instanceof l?f(u,function(e,t){n[t.cache]&&(d[t.cache]=n[t.cache].slice())}):f(u,function(t,s){var a=s.cache;f(s.props,function(e,t){if(!d[a]&&s.to){if("alpha"===e||null==n[e])return;d[a]=s.to(d._rgba)}d[a][t.idx]=i(n[e],t,!0)}),d[a]&&0>e.inArray(null,d[a].slice(0,3))&&(d[a][3]=1,s.from&&(d._rgba=s.from(d[a])))}),this):t},is:function(e){var i=l(e),s=!0,n=this;return f(u,function(e,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(e,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:t})),s}),s},_space:function(){var e=[],t=this;return f(u,function(i,s){t[s.cache]&&e.push(i)}),e.pop()},transition:function(e,t){var s=l(e),n=s._space(),a=u[n],o=0===this.alpha()?l("transparent"):this,r=o[a.cache]||a.to(o._rgba),h=r.slice();return s=s[a.cache],f(a.props,function(e,n){var a=n.idx,o=r[a],l=s[a],u=d[n.type]||{};null!==l&&(null===o?h[a]=l:(u.mod&&(l-o>u.mod/2?o+=u.mod:o-l>u.mod/2&&(o-=u.mod)),h[a]=i((l-o)*t+o,n)))}),this[n](h)},blend:function(t){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(t)._rgba;return l(e.map(i,function(e,t){return(1-s)*n[t]+s*e}))},toRgbaString:function(){var t="rgba(",i=e.map(this._rgba,function(e,t){return null==e?t>2?1:0:e});return 1===i[3]&&(i.pop(),t="rgb("),t+i.join()+")"},toHslaString:function(){var t="hsla(",i=e.map(this.hsla(),function(e,t){return null==e&&(e=t>2?1:0),t&&3>t&&(e=Math.round(100*e)+"%"),e});return 1===i[3]&&(i.pop(),t="hsl("),t+i.join()+")"},toHexString:function(t){var i=this._rgba.slice(),s=i.pop();return t&&i.push(~~(255*s)),"#"+e.map(i,function(e){return e=(e||0).toString(16),1===e.length?"0"+e:e}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,u.hsla.to=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t,i,s=e[0]/255,n=e[1]/255,a=e[2]/255,o=e[3],r=Math.max(s,n,a),h=Math.min(s,n,a),l=r-h,u=r+h,d=.5*u;return t=h===r?0:s===r?60*(n-a)/l+360:n===r?60*(a-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=d?l/u:l/(2-u),[Math.round(t)%360,i,d,null==o?1:o]},u.hsla.from=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t=e[0]/360,i=e[1],s=e[2],a=e[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,t+1/3)),Math.round(255*n(r,o,t)),Math.round(255*n(r,o,t-1/3)),a]},f(u,function(s,n){var a=n.props,o=n.cache,h=n.to,u=n.from;l.fn[s]=function(s){if(h&&!this[o]&&(this[o]=h(this._rgba)),s===t)return this[o].slice();var n,r=e.type(s),d="array"===r||"object"===r?s:arguments,c=this[o].slice();return f(a,function(e,t){var s=d["object"===r?e:t.idx];null==s&&(s=c[t.idx]),c[t.idx]=i(s,t)}),u?(n=l(u(c)),n[o]=c,n):l(c)},f(a,function(t,i){l.fn[t]||(l.fn[t]=function(n){var a,o=e.type(n),h="alpha"===t?this._hsla?"hsla":"rgba":s,l=this[h](),u=l[i.idx];return"undefined"===o?u:("function"===o&&(n=n.call(this,u),o=e.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=u+parseFloat(a[2])*("+"===a[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(t){var i=t.split(" ");f(i,function(t,i){e.cssHooks[i]={set:function(t,n){var a,o,r="";if("transparent"!==n&&("string"!==e.type(n)||(a=s(n)))){if(n=l(a||n),!c.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?t.parentNode:t;(""===r||"transparent"===r)&&o&&o.style;)try{r=e.css(o,"backgroundColor"),o=o.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{t.style[i]=n}catch(h){}}},e.fx.step[i]=function(t){t.colorInit||(t.start=l(t.elem,i),t.end=l(t.end),t.colorInit=!0),e.cssHooks[i].set(t.elem,t.start.transition(t.end,t.pos))}})},l.hook(o),e.cssHooks.borderColor={expand:function(e){var t={};return f(["Top","Right","Bottom","Left"],function(i,s){t["border"+s+"Color"]=e}),t}},a=e.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(b),function(){function t(t){var i,s,n=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[e.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function i(t,i){var s,a,o={};for(s in i)a=i[s],t[s]!==a&&(n[s]||(e.fx.step[s]||!isNaN(parseFloat(a)))&&(o[s]=a));return o}var s=["add","remove","toggle"],n={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,i){e.fx.step[i]=function(e){("none"!==e.end&&!e.setAttr||1===e.pos&&!e.setAttr)&&(b.style(e.elem,i,e.end),e.setAttr=!0)}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e.effects.animateClass=function(n,a,o,r){var h=e.speed(a,o,r);return this.queue(function(){var a,o=e(this),r=o.attr("class")||"",l=h.children?o.find("*").addBack():o;l=l.map(function(){var i=e(this);return{el:i,start:t(this)}}),a=function(){e.each(s,function(e,t){n[t]&&o[t+"Class"](n[t])})},a(),l=l.map(function(){return this.end=t(this.el[0]),this.diff=i(this.start,this.end),this}),o.attr("class",r),l=l.map(function(){var t=this,i=e.Deferred(),s=e.extend({},h,{queue:!1,complete:function(){i.resolve(t)}});return this.el.animate(this.diff,s),i.promise()}),e.when.apply(e,l.get()).done(function(){a(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),h.complete.call(o[0])})})},e.fn.extend({addClass:function(t){return function(i,s,n,a){return s?e.effects.animateClass.call(this,{add:i},s,n,a):t.apply(this,arguments)}}(e.fn.addClass),removeClass:function(t){return function(i,s,n,a){return arguments.length>1?e.effects.animateClass.call(this,{remove:i},s,n,a):t.apply(this,arguments)}}(e.fn.removeClass),toggleClass:function(t){return function(i,s,n,a,o){return"boolean"==typeof s||void 0===s?n?e.effects.animateClass.call(this,s?{add:i}:{remove:i},n,a,o):t.apply(this,arguments):e.effects.animateClass.call(this,{toggle:i},s,n,a)}}(e.fn.toggleClass),switchClass:function(t,i,s,n,a){return e.effects.animateClass.call(this,{add:i,remove:t},s,n,a)}})}(),function(){function t(t,i,s,n){return e.isPlainObject(t)&&(i=t,t=t.effect),t={effect:t},null==i&&(i={}),e.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||e.fx.speeds[i])&&(n=s,s=i,i={}),e.isFunction(s)&&(n=s,s=null),i&&e.extend(t,i),s=s||i.duration,t.duration=e.fx.off?0:"number"==typeof s?s:s in e.fx.speeds?e.fx.speeds[s]:e.fx.speeds._default,t.complete=n||i.complete,t}function i(t){return!t||"number"==typeof t||e.fx.speeds[t]?!0:"string"!=typeof t||e.effects.effect[t]?e.isFunction(t)?!0:"object"!=typeof t||t.effect?!1:!0:!0}e.extend(e.effects,{version:"1.11.4",save:function(e,t){for(var i=0;t.length>i;i++)null!==t[i]&&e.data(y+t[i],e[0].style[t[i]])},restore:function(e,t){var i,s;for(s=0;t.length>s;s++)null!==t[s]&&(i=e.data(y+t[s]),void 0===i&&(i=""),e.css(t[s],i))},setMode:function(e,t){return"toggle"===t&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var i,s;switch(e[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=e[0]/t.height}switch(e[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=e[1]/t.width}return{x:s,y:i}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var i={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},s=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:t.width(),height:t.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return t.wrap(s),(t[0]===a||e.contains(t[0],a))&&e(a).focus(),s=t.parent(),"static"===t.css("position")?(s.css({position:"relative"}),t.css({position:"relative"})):(e.extend(i,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,s){i[s]=t.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(n),s.css(i).show()},removeWrapper:function(t){var i=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===i||e.contains(t[0],i))&&e(i).focus()),t},setTransition:function(t,i,s,n){return n=n||{},e.each(i,function(e,i){var a=t.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),e.fn.extend({effect:function(){function i(t){function i(){e.isFunction(a)&&a.call(n[0]),e.isFunction(t)&&t()}var n=e(this),a=s.complete,r=s.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),i()):o.call(n[0],s,i)}var s=t.apply(this,arguments),n=s.mode,a=s.queue,o=e.effects.effect[s.effect];return e.fx.off||!o?n?this[n](s.duration,s.complete):this.each(function(){s.complete&&s.complete.call(this)}):a===!1?this.each(i):this.queue(a||"fx",i)},show:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="show",this.effect.call(this,n)}}(e.fn.show),hide:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="hide",this.effect.call(this,n)}}(e.fn.hide),toggle:function(e){return function(s){if(i(s)||"boolean"==typeof s)return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)}}(e.fn.toggle),cssUnit:function(t){var i=this.css(t),s=[];return e.each(["em","px","%","pt"],function(e,t){i.indexOf(t)>0&&(s=[parseFloat(i),t])}),s}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,i){t[i]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return 0===e||1===e?e:-Math.pow(2,8*(e-1))*Math.sin((80*(e-1)-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){for(var t,i=4;((t=Math.pow(2,--i))-1)/11>e;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*t-2)/22-e,2)}}),e.each(t,function(t,i){e.easing["easeIn"+t]=i,e.easing["easeOut"+t]=function(e){return 1-i(1-e)},e.easing["easeInOut"+t]=function(e){return.5>e?i(2*e)/2:1-i(-2*e+2)/2}})}(),e.effects,e.effects.effect.blind=function(t,i){var s,n,a,o=e(this),r=/up|down|vertical/,h=/up|left|vertical|horizontal/,l=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(o,t.mode||"hide"),d=t.direction||"up",c=r.test(d),p=c?"height":"width",f=c?"top":"left",m=h.test(d),g={},v="show"===u;o.parent().is(".ui-effects-wrapper")?e.effects.save(o.parent(),l):e.effects.save(o,l),o.show(),s=e.effects.createWrapper(o).css({overflow:"hidden"}),n=s[p](),a=parseFloat(s.css(f))||0,g[p]=v?n:0,m||(o.css(c?"bottom":"right",0).css(c?"top":"left","auto").css({position:"absolute"}),g[f]=v?a:n+a),v&&(s.css(p,0),m||s.css(f,a+n)),s.animate(g,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){"hide"===u&&o.hide(),e.effects.restore(o,l),e.effects.removeWrapper(o),i()}})},e.effects.effect.bounce=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(o,t.mode||"effect"),l="hide"===h,u="show"===h,d=t.direction||"up",c=t.distance,p=t.times||5,f=2*p+(u||l?1:0),m=t.duration/f,g=t.easing,v="up"===d||"down"===d?"top":"left",y="up"===d||"left"===d,b=o.queue(),_=b.length;for((u||l)&&r.push("opacity"),e.effects.save(o,r),o.show(),e.effects.createWrapper(o),c||(c=o["top"===v?"outerHeight":"outerWidth"]()/3),u&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,y?2*-c:2*c).animate(a,m,g)),l&&(c/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(y?"-=":"+=")+c,o.animate(n,m,g).animate(a,m,g),c=l?2*c:c/2;l&&(n={opacity:0},n[v]=(y?"-=":"+=")+c,o.animate(n,m,g)),o.queue(function(){l&&o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}),_>1&&b.splice.apply(b,[1,0].concat(b.splice(_,f+1))),o.dequeue()},e.effects.effect.clip=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(o,t.mode||"hide"),l="show"===h,u=t.direction||"vertical",d="vertical"===u,c=d?"height":"width",p=d?"top":"left",f={};e.effects.save(o,r),o.show(),s=e.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[c](),l&&(n.css(c,0),n.css(p,a/2)),f[c]=l?a:0,f[p]=l?0:a/2,n.animate(f,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){l||o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}})},e.effects.effect.drop=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","opacity","height","width"],o=e.effects.setMode(n,t.mode||"hide"),r="show"===o,h=t.direction||"left",l="up"===h||"down"===h?"top":"left",u="up"===h||"left"===h?"pos":"neg",d={opacity:r?1:0};e.effects.save(n,a),n.show(),e.effects.createWrapper(n),s=t.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(l,"pos"===u?-s:s),d[l]=(r?"pos"===u?"+=":"-=":"pos"===u?"-=":"+=")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.explode=function(t,i){function s(){b.push(this),b.length===d*c&&n()}function n(){p.css({visibility:"visible"}),e(b).remove(),m||p.hide(),i()}var a,o,r,h,l,u,d=t.pieces?Math.round(Math.sqrt(t.pieces)):3,c=d,p=e(this),f=e.effects.setMode(p,t.mode||"hide"),m="show"===f,g=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/c),y=Math.ceil(p.outerHeight()/d),b=[];for(a=0;d>a;a++)for(h=g.top+a*y,u=a-(d-1)/2,o=0;c>o;o++)r=g.left+o*v,l=o-(c-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*y}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:y,left:r+(m?l*v:0),top:h+(m?u*y:0),opacity:m?0:1}).animate({left:r+(m?0:l*v),top:h+(m?0:u*y),opacity:m?1:0},t.duration||500,t.easing,s)},e.effects.effect.fade=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:t.duration,easing:t.easing,complete:i})},e.effects.effect.fold=function(t,i){var s,n,a=e(this),o=["position","top","bottom","left","right","height","width"],r=e.effects.setMode(a,t.mode||"hide"),h="show"===r,l="hide"===r,u=t.size||15,d=/([0-9]+)%/.exec(u),c=!!t.horizFirst,p=h!==c,f=p?["width","height"]:["height","width"],m=t.duration/2,g={},v={};e.effects.save(a,o),a.show(),s=e.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],d&&(u=parseInt(d[1],10)/100*n[l?0:1]),h&&s.css(c?{height:0,width:u}:{height:u,width:0}),g[f[0]]=h?n[0]:u,v[f[1]]=h?n[1]:0,s.animate(g,m,t.easing).animate(v,m,t.easing,function(){l&&a.hide(),e.effects.restore(a,o),e.effects.removeWrapper(a),i()})},e.effects.effect.highlight=function(t,i){var s=e(this),n=["backgroundImage","backgroundColor","opacity"],a=e.effects.setMode(s,t.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),e.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===a&&s.hide(),e.effects.restore(s,n),i()}})},e.effects.effect.size=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],h=["position","top","bottom","left","right","overflow","opacity"],l=["width","height","overflow"],u=["fontSize"],d=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],c=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),f=t.restore||"effect"!==p,m=t.scale||"both",g=t.origin||["middle","center"],v=o.css("position"),y=f?r:h,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===t.mode&&"show"===p?(o.from=t.to||b,o.to=t.from||s):(o.from=t.from||("show"===p?b:s),o.to=t.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===m||"both"===m)&&(a.from.y!==a.to.y&&(y=y.concat(d),o.from=e.effects.setTransition(o,d,a.from.y,o.from),o.to=e.effects.setTransition(o,d,a.to.y,o.to)),a.from.x!==a.to.x&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,a.from.x,o.from),o.to=e.effects.setTransition(o,c,a.to.x,o.to))),("content"===m||"both"===m)&&a.from.y!==a.to.y&&(y=y.concat(u).concat(l),o.from=e.effects.setTransition(o,u,a.from.y,o.from),o.to=e.effects.setTransition(o,u,a.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),g&&(n=e.effects.getBaseline(g,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===m||"both"===m)&&(d=d.concat(["marginTop","marginBottom"]).concat(u),c=c.concat(["marginLeft","marginRight"]),l=r.concat(d).concat(c),o.find("*[width]").each(function(){var i=e(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};
11
- f&&e.effects.save(i,l),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=e.effects.setTransition(i,d,a.from.y,i.from),i.to=e.effects.setTransition(i,d,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=e.effects.setTransition(i,c,a.from.x,i.from),i.to=e.effects.setTransition(i,c,a.to.x,i.to)),i.css(i.from),i.animate(i.to,t.duration,t.easing,function(){f&&e.effects.restore(i,l)})})),o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),e.effects.restore(o,y),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,i){var s=parseInt(i,10),n=e?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),e.effects.removeWrapper(o),i()}})},e.effects.effect.scale=function(t,i){var s=e(this),n=e.extend(!0,{},t),a=e.effects.setMode(s,t.mode||"effect"),o=parseInt(t.percent,10)||(0===parseInt(t.percent,10)?0:"hide"===a?0:100),r=t.direction||"both",h=t.origin,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},u={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=h||["middle","center"],n.restore=!0),n.from=t.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:l),n.to={height:l.height*u.y,width:l.width*u.x,outerHeight:l.outerHeight*u.y,outerWidth:l.outerWidth*u.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},e.effects.effect.puff=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||"hide"),a="hide"===n,o=parseInt(t.percent,10)||150,r=o/100,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?h:{height:h.height*r,width:h.width*r,outerHeight:h.outerHeight*r,outerWidth:h.outerWidth*r}}),s.effect(t)},e.effects.effect.pulsate=function(t,i){var s,n=e(this),a=e.effects.setMode(n,t.mode||"show"),o="show"===a,r="hide"===a,h=o||"hide"===a,l=2*(t.times||5)+(h?1:0),u=t.duration/l,d=0,c=n.queue(),p=c.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),d=1),s=1;l>s;s++)n.animate({opacity:d},u,t.easing),d=1-d;n.animate({opacity:d},u,t.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&c.splice.apply(c,[1,0].concat(c.splice(p,l+1))),n.dequeue()},e.effects.effect.shake=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","height","width"],o=e.effects.setMode(n,t.mode||"effect"),r=t.direction||"left",h=t.distance||20,l=t.times||3,u=2*l+1,d=Math.round(t.duration/u),c="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},m={},g={},v=n.queue(),y=v.length;for(e.effects.save(n,a),n.show(),e.effects.createWrapper(n),f[c]=(p?"-=":"+=")+h,m[c]=(p?"+=":"-=")+2*h,g[c]=(p?"-=":"+=")+2*h,n.animate(f,d,t.easing),s=1;l>s;s++)n.animate(m,d,t.easing).animate(g,d,t.easing);n.animate(m,d,t.easing).animate(f,d/2,t.easing).queue(function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}),y>1&&v.splice.apply(v,[1,0].concat(v.splice(y,u+1))),n.dequeue()},e.effects.effect.slide=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","width","height"],o=e.effects.setMode(n,t.mode||"show"),r="show"===o,h=t.direction||"left",l="up"===h||"down"===h?"top":"left",u="up"===h||"left"===h,d={};e.effects.save(n,a),n.show(),s=t.distance||n["top"===l?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(l,u?isNaN(s)?"-"+s:-s:s),d[l]=(r?u?"+=":"-=":u?"-=":"+=")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.transfer=function(t,i){var s=e(this),n=e(t.to),a="fixed"===n.css("position"),o=e("body"),r=a?o.scrollTop():0,h=a?o.scrollLeft():0,l=n.offset(),u={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},d=s.offset(),c=e("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(t.className).css({top:d.top-r,left:d.left-h,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(u,t.duration,t.easing,function(){c.remove(),i()})},e.widget("ui.progressbar",{version:"1.11.4",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return void 0===e?this.options.value:(this.options.value=this._constrainedValue(e),this._refreshValue(),void 0)},_constrainedValue:function(e){return void 0===e&&(e=this.options.value),this.indeterminate=e===!1,"number"!=typeof e&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){"max"===e&&(t=Math.max(this.min,t)),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass("ui-corner-right",t===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=e("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}}),e.widget("ui.selectable",e.ui.mouse,{version:"1.11.4",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),i=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger("start",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=e.data(this,"selectable-item");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,"selectable-item");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",t,{selecting:n.element}):i._trigger("unselecting",t,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):"fit"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",t,{unselected:s.element})}),e(".ui-selecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",t,{selected:s.element})}),this._trigger("stop",t),this.helper.remove(),!1}}),e.widget("ui.selectmenu",{version:"1.11.4",defaultElement:"<select>",options:{appendTo:null,disabled:null,icons:{button:"ui-icon-triangle-1-s"},position:{my:"left top",at:"left bottom",collision:"none"},width:null,change:null,close:null,focus:null,open:null,select:null},_create:function(){var e=this.element.uniqueId().attr("id");this.ids={element:e,button:e+"-button",menu:e+"-menu"},this._drawButton(),this._drawMenu(),this.options.disabled&&this.disable()},_drawButton:function(){var t=this;this.label=e("label[for='"+this.ids.element+"']").attr("for",this.ids.button),this._on(this.label,{click:function(e){this.button.focus(),e.preventDefault()}}),this.element.hide(),this.button=e("<span>",{"class":"ui-selectmenu-button ui-widget ui-state-default ui-corner-all",tabindex:this.options.disabled?-1:0,id:this.ids.button,role:"combobox","aria-expanded":"false","aria-autocomplete":"list","aria-owns":this.ids.menu,"aria-haspopup":"true"}).insertAfter(this.element),e("<span>",{"class":"ui-icon "+this.options.icons.button}).prependTo(this.button),this.buttonText=e("<span>",{"class":"ui-selectmenu-text"}).appendTo(this.button),this._setText(this.buttonText,this.element.find("option:selected").text()),this._resizeButton(),this._on(this.button,this._buttonEvents),this.button.one("focusin",function(){t.menuItems||t._refreshMenu()}),this._hoverable(this.button),this._focusable(this.button)},_drawMenu:function(){var t=this;this.menu=e("<ul>",{"aria-hidden":"true","aria-labelledby":this.ids.button,id:this.ids.menu}),this.menuWrap=e("<div>",{"class":"ui-selectmenu-menu ui-front"}).append(this.menu).appendTo(this._appendTo()),this.menuInstance=this.menu.menu({role:"listbox",select:function(e,i){e.preventDefault(),t._setSelection(),t._select(i.item.data("ui-selectmenu-item"),e)},focus:function(e,i){var s=i.item.data("ui-selectmenu-item");null!=t.focusIndex&&s.index!==t.focusIndex&&(t._trigger("focus",e,{item:s}),t.isOpen||t._select(s,e)),t.focusIndex=s.index,t.button.attr("aria-activedescendant",t.menuItems.eq(s.index).attr("id"))}}).menu("instance"),this.menu.addClass("ui-corner-bottom").removeClass("ui-corner-all"),this.menuInstance._off(this.menu,"mouseleave"),this.menuInstance._closeOnDocumentClick=function(){return!1},this.menuInstance._isDivider=function(){return!1}},refresh:function(){this._refreshMenu(),this._setText(this.buttonText,this._getSelectedItem().text()),this.options.width||this._resizeButton()},_refreshMenu:function(){this.menu.empty();var e,t=this.element.find("option");t.length&&(this._parseOptions(t),this._renderMenu(this.menu,this.items),this.menuInstance.refresh(),this.menuItems=this.menu.find("li").not(".ui-selectmenu-optgroup"),e=this._getSelectedItem(),this.menuInstance.focus(null,e),this._setAria(e.data("ui-selectmenu-item")),this._setOption("disabled",this.element.prop("disabled")))},open:function(e){this.options.disabled||(this.menuItems?(this.menu.find(".ui-state-focus").removeClass("ui-state-focus"),this.menuInstance.focus(null,this._getSelectedItem())):this._refreshMenu(),this.isOpen=!0,this._toggleAttr(),this._resizeMenu(),this._position(),this._on(this.document,this._documentClick),this._trigger("open",e))},_position:function(){this.menuWrap.position(e.extend({of:this.button},this.options.position))},close:function(e){this.isOpen&&(this.isOpen=!1,this._toggleAttr(),this.range=null,this._off(this.document),this._trigger("close",e))},widget:function(){return this.button},menuWidget:function(){return this.menu},_renderMenu:function(t,i){var s=this,n="";e.each(i,function(i,a){a.optgroup!==n&&(e("<li>",{"class":"ui-selectmenu-optgroup ui-menu-divider"+(a.element.parent("optgroup").prop("disabled")?" ui-state-disabled":""),text:a.optgroup}).appendTo(t),n=a.optgroup),s._renderItemData(t,a)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-selectmenu-item",t)},_renderItem:function(t,i){var s=e("<li>");return i.disabled&&s.addClass("ui-state-disabled"),this._setText(s,i.label),s.appendTo(t)},_setText:function(e,t){t?e.text(t):e.html("&#160;")},_move:function(e,t){var i,s,n=".ui-menu-item";this.isOpen?i=this.menuItems.eq(this.focusIndex):(i=this.menuItems.eq(this.element[0].selectedIndex),n+=":not(.ui-state-disabled)"),s="first"===e||"last"===e?i["first"===e?"prevAll":"nextAll"](n).eq(-1):i[e+"All"](n).eq(0),s.length&&this.menuInstance.focus(t,s)},_getSelectedItem:function(){return this.menuItems.eq(this.element[0].selectedIndex)},_toggle:function(e){this[this.isOpen?"close":"open"](e)},_setSelection:function(){var e;this.range&&(window.getSelection?(e=window.getSelection(),e.removeAllRanges(),e.addRange(this.range)):this.range.select(),this.button.focus())},_documentClick:{mousedown:function(t){this.isOpen&&(e(t.target).closest(".ui-selectmenu-menu, #"+this.ids.button).length||this.close(t))}},_buttonEvents:{mousedown:function(){var e;window.getSelection?(e=window.getSelection(),e.rangeCount&&(this.range=e.getRangeAt(0))):this.range=document.selection.createRange()},click:function(e){this._setSelection(),this._toggle(e)},keydown:function(t){var i=!0;switch(t.keyCode){case e.ui.keyCode.TAB:case e.ui.keyCode.ESCAPE:this.close(t),i=!1;break;case e.ui.keyCode.ENTER:this.isOpen&&this._selectFocusedItem(t);break;case e.ui.keyCode.UP:t.altKey?this._toggle(t):this._move("prev",t);break;case e.ui.keyCode.DOWN:t.altKey?this._toggle(t):this._move("next",t);break;case e.ui.keyCode.SPACE:this.isOpen?this._selectFocusedItem(t):this._toggle(t);break;case e.ui.keyCode.LEFT:this._move("prev",t);break;case e.ui.keyCode.RIGHT:this._move("next",t);break;case e.ui.keyCode.HOME:case e.ui.keyCode.PAGE_UP:this._move("first",t);break;case e.ui.keyCode.END:case e.ui.keyCode.PAGE_DOWN:this._move("last",t);break;default:this.menu.trigger(t),i=!1}i&&t.preventDefault()}},_selectFocusedItem:function(e){var t=this.menuItems.eq(this.focusIndex);t.hasClass("ui-state-disabled")||this._select(t.data("ui-selectmenu-item"),e)},_select:function(e,t){var i=this.element[0].selectedIndex;this.element[0].selectedIndex=e.index,this._setText(this.buttonText,e.label),this._setAria(e),this._trigger("select",t,{item:e}),e.index!==i&&this._trigger("change",t,{item:e}),this.close(t)},_setAria:function(e){var t=this.menuItems.eq(e.index).attr("id");this.button.attr({"aria-labelledby":t,"aria-activedescendant":t}),this.menu.attr("aria-activedescendant",t)},_setOption:function(e,t){"icons"===e&&this.button.find("span.ui-icon").removeClass(this.options.icons.button).addClass(t.button),this._super(e,t),"appendTo"===e&&this.menuWrap.appendTo(this._appendTo()),"disabled"===e&&(this.menuInstance.option("disabled",t),this.button.toggleClass("ui-state-disabled",t).attr("aria-disabled",t),this.element.prop("disabled",t),t?(this.button.attr("tabindex",-1),this.close()):this.button.attr("tabindex",0)),"width"===e&&this._resizeButton()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_toggleAttr:function(){this.button.toggleClass("ui-corner-top",this.isOpen).toggleClass("ui-corner-all",!this.isOpen).attr("aria-expanded",this.isOpen),this.menuWrap.toggleClass("ui-selectmenu-open",this.isOpen),this.menu.attr("aria-hidden",!this.isOpen)},_resizeButton:function(){var e=this.options.width;e||(e=this.element.show().outerWidth(),this.element.hide()),this.button.outerWidth(e)},_resizeMenu:function(){this.menu.outerWidth(Math.max(this.button.outerWidth(),this.menu.width("").outerWidth()+1))},_getCreateOptions:function(){return{disabled:this.element.prop("disabled")}},_parseOptions:function(t){var i=[];t.each(function(t,s){var n=e(s),a=n.parent("optgroup");i.push({element:n,index:t,value:n.val(),label:n.text(),optgroup:a.attr("label")||"",disabled:a.prop("disabled")||n.prop("disabled")})}),this.items=i},_destroy:function(){this.menuWrap.remove(),this.button.remove(),this.element.show(),this.element.removeUniqueId(),this.label.attr("for",this.ids.element)}}),e.widget("ui.slider",e.ui.mouse,{version:"1.11.4",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},numPages:5,_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this._calculateNewMax(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var t,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),a="<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),t=n.length;i>t;t++)o.push(a);this.handles=n.add(e(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(t){e(this).data("ui-slider-handle-index",t)})},_createRange:function(){var t=this.options,i="";t.range?(t.range===!0&&(t.values?t.values.length&&2!==t.values.length?t.values=[t.values[0],t.values[0]]:e.isArray(t.values)&&(t.values=t.values.slice(0)):t.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=e("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===t.range||"max"===t.range?" ui-slider-range-"+t.range:""))):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(t){var i,s,n,a,o,r,h,l,u=this,d=this.options;return d.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:t.pageX,y:t.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var i=Math.abs(s-u.values(t));(n>i||n===i&&(t===u._lastChangedValue||u.values(t)===d.min))&&(n=i,a=e(this),o=t)}),r=this._start(t,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass("ui-state-active").focus(),h=a.offset(),l=!e(t.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:t.pageX-h.left-a.width()/2,top:t.pageY-h.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},i=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,i),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,i,s,n,a;return"horizontal"===this.orientation?(t=this.elementSize.width,i=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,i=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/t,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(e,t){var i={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(t),i.values=this.values()),this._trigger("start",e,i)},_slide:function(e,t,i){var s,n,a;this.options.values&&this.options.values.length?(s=this.values(t?0:1),2===this.options.values.length&&this.options.range===!0&&(0===t&&i>s||1===t&&s>i)&&(i=s),i!==this.values(t)&&(n=this.values(),n[t]=i,a=this._trigger("slide",e,{handle:this.handles[t],value:i,values:n}),s=this.values(t?0:1),a!==!1&&this.values(t,i))):i!==this.value()&&(a=this._trigger("slide",e,{handle:this.handles[t],value:i}),a!==!1&&this.value(i))},_stop:function(e,t){var i={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(t),i.values=this.values()),this._trigger("stop",e,i)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(t),i.values=this.values()),this._lastChangedValue=t,this._trigger("change",e,i)}},value:function(e){return arguments.length?(this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0),void 0):this._value()},values:function(t,i){var s,n,a;if(arguments.length>1)return this.options.values[t]=this._trimAlignValue(i),this._refreshValue(),this._change(null,t),void 0;if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(t,i){var s,n=0;switch("range"===t&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),e.isArray(this.options.values)&&(n=this.options.values.length),"disabled"===t&&this.element.toggleClass("ui-state-disabled",!!i),this._super(t,i),t){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue(),this.handles.css("horizontal"===i?"bottom":"left","");break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"step":case"min":case"max":this._animateOff=!0,this._calculateNewMax(),this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e)},_values:function(e){var t,i,s;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(e){if(this._valueMin()>=e)return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,i=(e-this._valueMin())%t,s=e-i;return 2*Math.abs(i)>=t&&(s+=i>0?t:-t),parseFloat(s.toFixed(5))},_calculateNewMax:function(){var e=this.options.max,t=this._valueMin(),i=this.options.step,s=Math.floor(+(e-t).toFixed(this._precision())/i)*i;e=s+t,this.max=parseFloat(e.toFixed(this._precision()))},_precision:function(){var e=this._precisionOf(this.options.step);return null!==this.options.min&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=""+e,i=t.indexOf(".");return-1===i?0:t.length-i-1},_valueMin:function(){return this.options.min},_valueMax:function(){return this.max},_refreshValue:function(){var t,i,s,n,a,o=this.options.range,r=this.options,h=this,l=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((h.values(s)-h._valueMin())/(h._valueMax()-h._valueMin())),u["horizontal"===h.orientation?"left":"bottom"]=i+"%",e(this).stop(1,1)[l?"animate":"css"](u,r.animate),h.options.range===!0&&("horizontal"===h.orientation?(0===s&&h.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({width:i-t+"%"},{queue:!1,duration:r.animate})):(0===s&&h.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({height:i-t+"%"},{queue:!1,duration:r.animate}))),t=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[l?"animate":"css"](u,r.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},r.animate),"max"===o&&"horizontal"===this.orientation&&this.range[l?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},r.animate),"max"===o&&"vertical"===this.orientation&&this.range[l?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(t){var i,s,n,a,o=e(t.target).data("ui-slider-handle-index");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(t.preventDefault(),!this._keySliding&&(this._keySliding=!0,e(t.target).addClass("ui-state-active"),i=this._start(t,o),i===!1))return}switch(a=this.options.step,s=n=this.options.values&&this.options.values.length?this.values(o):this.value(),t.keyCode){case e.ui.keyCode.HOME:n=this._valueMin();break;case e.ui.keyCode.END:n=this._valueMax();break;case e.ui.keyCode.PAGE_UP:n=this._trimAlignValue(s+(this._valueMax()-this._valueMin())/this.numPages);break;case e.ui.keyCode.PAGE_DOWN:n=this._trimAlignValue(s-(this._valueMax()-this._valueMin())/this.numPages);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(s===this._valueMax())return;n=this._trimAlignValue(s+a);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(s===this._valueMin())return;n=this._trimAlignValue(s-a)}this._slide(t,o,n)},keyup:function(t){var i=e(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,i),this._change(t,i),e(t.target).removeClass("ui-state-active"))}}}),e.widget("ui.sortable",e.ui.mouse,{version:"1.11.4",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(e,t,i){return e>=t&&t+i>e},_isFloating:function(e){return/left|right/.test(e.css("float"))||/inline|table-cell/.test(e.css("display"))},_create:function(){this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(e,t){this._super(e,t),"handle"===e&&this._setHandleClassName()},_setHandleClassName:function(){this.element.find(".ui-sortable-handle").removeClass("ui-sortable-handle"),e.each(this.items,function(){(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item).addClass("ui-sortable-handle")})},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").find(".ui-sortable-handle").removeClass("ui-sortable-handle"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(t,i){var s=null,n=!1,a=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(t),e(t.target).parents().each(function(){return e.data(this,a.widgetName+"-item")===a?(s=e(this),!1):void 0}),e.data(t.target,a.widgetName+"-item")===a&&(s=e(t.target)),s?!this.options.handle||i||(e(this.options.handle,s).find("*").addBack().each(function(){this===t.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(t,i,s){var n,a,o=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),o.containment&&this._setContainment(),o.cursor&&"auto"!==o.cursor&&(a=this.document.find("body"),this.storedCursor=a.css("cursor"),a.css("cursor",o.cursor),this.storedStylesheet=e("<style>*{ cursor: "+o.cursor+" !important; }</style>").appendTo(a)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",t,this._uiHash(this));
12
- return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var i,s,n,a,o=this.options,r=!1;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<o.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+o.scrollSpeed:t.pageY-this.overflowOffset.top<o.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-o.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<o.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+o.scrollSpeed:t.pageX-this.overflowOffset.left<o.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-o.scrollSpeed)):(t.pageY-this.document.scrollTop()<o.scrollSensitivity?r=this.document.scrollTop(this.document.scrollTop()-o.scrollSpeed):this.window.height()-(t.pageY-this.document.scrollTop())<o.scrollSensitivity&&(r=this.document.scrollTop(this.document.scrollTop()+o.scrollSpeed)),t.pageX-this.document.scrollLeft()<o.scrollSensitivity?r=this.document.scrollLeft(this.document.scrollLeft()-o.scrollSpeed):this.window.width()-(t.pageX-this.document.scrollLeft())<o.scrollSensitivity&&(r=this.document.scrollLeft(this.document.scrollLeft()+o.scrollSpeed))),r!==!1&&e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],a=this._intersectsWithPointer(s),a&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===a?"next":"prev"]()[0]!==n&&!e.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!e.contains(this.element[0],n):!0)){if(this.direction=1===a?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,i){if(t){if(e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t),this.options.revert){var s=this,n=this.placeholder.offset(),a=this.options.axis,o={};a&&"x"!==a||(o.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),a&&"y"!==a||(o.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,e(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){s._clear(t)})}else this._clear(t,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},e(i).each(function(){var i=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);i&&s.push((t.key||i[1]+"[]")+"="+(t.key&&t.expression?i[1]:i[2]))}),!s.length&&t.key&&s.push(t.key+"="),s.join("&")},toArray:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},i.each(function(){s.push(e(t.item||this).attr(t.attribute||"id")||"")}),s},_intersectsWith:function(e){var t=this.positionAbs.left,i=t+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,a=e.left,o=a+e.width,r=e.top,h=r+e.height,l=this.offset.click.top,u=this.offset.click.left,d="x"===this.options.axis||s+l>r&&h>s+l,c="y"===this.options.axis||t+u>a&&o>t+u,p=d&&c;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?p:t+this.helperProportions.width/2>a&&o>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(e){var t="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top,e.height),i="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left,e.width),s=t&&i,n=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return s?this.floating?a&&"right"===a||"down"===n?2:1:n&&("down"===n?2:1):!1},_intersectsWithSides:function(e){var t=this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&t||"up"===s&&!t)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return 0!==e&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return 0!==e&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){function i(){r.push(this)}var s,n,a,o,r=[],h=[],l=this._connectWith();if(l&&t)for(s=l.length-1;s>=0;s--)for(a=e(l[s],this.document[0]),n=a.length-1;n>=0;n--)o=e.data(a[n],this.widgetFullName),o&&o!==this&&!o.options.disabled&&h.push([e.isFunction(o.options.items)?o.options.items.call(o.element):e(o.options.items,o.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),o]);for(h.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return e(r)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var i=0;t.length>i;i++)if(t[i]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var i,s,n,a,o,r,h,l,u=this.items,d=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],c=this._connectWith();if(c&&this.ready)for(i=c.length-1;i>=0;i--)for(n=e(c[i],this.document[0]),s=n.length-1;s>=0;s--)a=e.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&(d.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a));for(i=d.length-1;i>=0;i--)for(o=d[i][1],r=d[i][0],s=0,l=r.length;l>s;s++)h=e(r[s]),h.data(this.widgetName+"-item",o),u.push({item:h,instance:o,width:0,height:0,left:0,top:0})},refreshPositions:function(t){this.floating=this.items.length?"x"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,a;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?e(this.options.toleranceElement,s.item):s.item,t||(s.width=n.outerWidth(),s.height=n.outerHeight()),a=n.offset(),s.left=a.left,s.top=a.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)a=this.containers[i].element.offset(),this.containers[i].containerCache.left=a.left,this.containers[i].containerCache.top=a.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var i,s=t.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=t.currentItem[0].nodeName.toLowerCase(),n=e("<"+s+">",t.document[0]).addClass(i||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tbody"===s?t._createTrPlaceholder(t.currentItem.find("tr").eq(0),e("<tr>",t.document[0]).appendTo(n)):"tr"===s?t._createTrPlaceholder(t.currentItem,n):"img"===s&&n.attr("src",t.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(e,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10)))}}),t.placeholder=e(s.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),s.placeholder.update(t,t.placeholder)},_createTrPlaceholder:function(t,i){var s=this;t.children().each(function(){e("<td>&#160;</td>",s.document[0]).attr("colspan",e(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(t){var i,s,n,a,o,r,h,l,u,d,c=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!e.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(c&&e.contains(this.containers[i].element[0],c.element[0]))continue;c=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0);if(c)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",t,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,a=null,u=c.floating||this._isFloating(this.currentItem),o=u?"left":"top",r=u?"width":"height",d=u?"clientX":"clientY",s=this.items.length-1;s>=0;s--)e.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(h=this.items[s].item.offset()[o],l=!1,t[d]-h>this.items[s][r]/2&&(l=!0),n>Math.abs(t[d]-h)&&(n=Math.abs(t[d]-h),a=this.items[s],this.direction=l?"up":"down"));if(!a&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",t,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;a?this._rearrange(t,a,null,!0):this._rearrange(t,null,this.containers[p].element,!0),this._trigger("change",t,this._uiHash()),this.containers[p]._trigger("change",t,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",t,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||e("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.width():this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(t=e(n.containment)[0],i=e(n.containment).offset(),s="hidden"!==e(t).css("overflow"),this.containment=[i.left+(parseInt(e(t).css("borderLeftWidth"),10)||0)+(parseInt(e(t).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(e(t).css("borderTopWidth"),10)||0)+(parseInt(e(t).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css("borderLeftWidth"),10)||0)-(parseInt(e(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css("borderTopWidth"),10)||0)-(parseInt(e(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():a?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():a?0:n.scrollLeft())*s}},_generatePosition:function(t){var i,s,n=this.options,a=t.pageX,o=t.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(a=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(a=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1],o=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((a-this.originalPageX)/n.grid[0])*n.grid[0],a=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(e,t,i,s){i?i[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(e,t){function i(e,t,i){return function(s){i._trigger(e,s,t._uiHash(t))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!t&&n.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||t||n.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(t||(n.push(function(e){this._trigger("remove",e,this._uiHash())}),n.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)t||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,t||this._trigger("beforeStop",e,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!t){for(s=0;n.length>s;s++)n[s].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var i=t||this;return{helper:i.helper,placeholder:i.placeholder||e([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:t?t.element:null}}}),e.widget("ui.spinner",{version:"1.11.4",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},i=this.element;return e.each(["min","max","step"],function(e,s){var n=i.attr(s);void 0!==n&&n.length&&(t[s]=n)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e),void 0)},mousewheel:function(e,t){if(t){if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()}},"mousedown .ui-spinner-button":function(t){function i(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(t)!==!1&&this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){return e(t.currentTarget).hasClass("ui-state-active")?this._start(t)===!1?!1:(this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*e.height())&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var i=this.options,s=e.ui.keyCode;switch(t.keyCode){case s.UP:return this._repeat(null,1,t),!0;case s.DOWN:return this._repeat(null,-1,t),!0;case s.PAGE_UP:return this._repeat(null,i.page,t),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,t),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(e){return this.spinning||this._trigger("start",e)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(e,t,i){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,i)},e),this._spin(t*this.options.step,i)},_spin:function(e,t){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+e*this._increment(this.counter)),this.spinning&&this._trigger("spin",t,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(t){var i=this.options.incremental;return i?e.isFunction(i)?i(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return null!==this.options.min&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=""+e,i=t.indexOf(".");return-1===i?0:t.length-i-1},_adjustValue:function(e){var t,i,s=this.options;return t=null!==s.min?s.min:0,i=e-t,i=Math.round(i/s.step)*s.step,e=t+i,e=parseFloat(e.toFixed(this._precision())),null!==s.max&&e>s.max?s.max:null!==s.min&&s.min>e?s.min:e},_stop:function(e){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e))},_setOption:function(e,t){if("culture"===e||"numberFormat"===e){var i=this._parse(this.element.val());return this.options[e]=t,this.element.val(this._format(i)),void 0}("max"===e||"min"===e||"step"===e)&&"string"==typeof t&&(t=this._parse(t)),"icons"===e&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(t.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(t.down)),this._super(e,t),"disabled"===e&&(this.widget().toggleClass("ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable"))},_setOptions:h(function(e){this._super(e)}),_parse:function(e){return"string"==typeof e&&""!==e&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),""===e||isNaN(e)?null:e},_format:function(e){return""===e?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var e=this.value();return null===e?!1:e===this._adjustValue(e)},_value:function(e,t){var i;""!==e&&(i=this._parse(e),null!==i&&(t||(i=this._adjustValue(i)),e=this._format(i))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:h(function(e){this._stepUp(e)}),_stepUp:function(e){this._start()&&(this._spin((e||1)*this.options.step),this._stop())},stepDown:h(function(e){this._stepDown(e)}),_stepDown:function(e){this._start()&&(this._spin((e||1)*-this.options.step),this._stop())},pageUp:h(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:h(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){return arguments.length?(h(this._value).call(this,e),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),e.widget("ui.tabs",{version:"1.11.4",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var e=/#.*$/;return function(t){var i,s;t=t.cloneNode(!1),i=t.href.replace(e,""),s=location.href.replace(e,"");try{i=decodeURIComponent(i)}catch(n){}try{s=decodeURIComponent(s)}catch(n){}return t.hash.length>1&&i===s}}(),_create:function(){var t=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible),this._processTabs(),i.active=this._initialActive(),e.isArray(i.disabled)&&(i.disabled=e.unique(i.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):e(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var t=this.options.active,i=this.options.collapsible,s=location.hash.substring(1);return null===t&&(s&&this.tabs.each(function(i,n){return e(n).attr("aria-controls")===s?(t=i,!1):void 0}),null===t&&(t=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===t||-1===t)&&(t=this.tabs.length?0:!1)),t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),-1===t&&(t=i?!1:0)),!i&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var i=e(this.document[0].activeElement).closest("li"),s=this.tabs.index(i),n=!0;if(!this._handlePageNav(t)){switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:s++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:n=!1,s--;break;case e.ui.keyCode.END:s=this.anchors.length-1;break;case e.ui.keyCode.HOME:s=0;break;case e.ui.keyCode.SPACE:return t.preventDefault(),clearTimeout(this.activating),this._activate(s),void 0;case e.ui.keyCode.ENTER:return t.preventDefault(),clearTimeout(this.activating),this._activate(s===this.options.active?!1:s),void 0;default:return}t.preventDefault(),clearTimeout(this.activating),s=this._focusNextTab(s,n),t.ctrlKey||t.metaKey||(i.attr("aria-selected","false"),this.tabs.eq(s).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",s)},this.delay))}},_panelKeydown:function(t){this._handlePageNav(t)||t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){return t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(t,i){function s(){return t>n&&(t=0),0>t&&(t=n),t}for(var n=this.tabs.length-1;-1!==e.inArray(s(),this.options.disabled);)t=i?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):"disabled"===e?(this._setupDisabled(t),void 0):(this._super(e,t),"collapsible"===e&&(this.element.toggleClass("ui-tabs-collapsible",t),t||this.options.active!==!1||this._activate(0)),"event"===e&&this._setupEvents(t),"heightStyle"===e&&this._setupHeightStyle(t),void 0)},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,i=this.tablist.children(":has(a[href])");t.disabled=e.map(i.filter(".ui-state-disabled"),function(e){return i.index(e)}),this._processTabs(),t.active!==!1&&this.anchors.length?this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=e()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this,i=this.tabs,s=this.anchors,n=this.panels;
13
- this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist").delegate("> li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(i,s){var n,a,o,r=e(s).uniqueId().attr("id"),h=e(s).closest("li"),l=h.attr("aria-controls");t._isLocal(s)?(n=s.hash,o=n.substring(1),a=t.element.find(t._sanitizeSelector(n))):(o=h.attr("aria-controls")||e({}).uniqueId()[0].id,n="#"+o,a=t.element.find(n),a.length||(a=t._createPanel(o),a.insertAfter(t.panels[i-1]||t.tablist)),a.attr("aria-live","polite")),a.length&&(t.panels=t.panels.add(a)),l&&h.data("ui-tabs-aria-controls",l),h.attr({"aria-controls":o,"aria-labelledby":r}),a.attr("aria-labelledby",r)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel"),i&&(this._off(i.not(this.tabs)),this._off(s.not(this.anchors)),this._off(n.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var i,s=0;i=this.tabs[s];s++)t===!0||-1!==e.inArray(s,t)?e(i).addClass("ui-state-disabled").attr("aria-disabled","true"):e(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var i={};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(e){e.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var i,s=this.element.parent();"fill"===t?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=e(this),s=t.css("position");"absolute"!==s&&"fixed"!==s&&(i-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,i-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===t&&(i=0,this.panels.each(function(){i=Math.max(i,e(this).height("").height())}).height(i))},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?e():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):e(),u={oldTab:s,oldPanel:l,newTab:r?e():a,newPanel:h};t.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",t,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?e():a,this.xhr&&this.xhr.abort(),l.length||h.length||e.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),t),this._toggle(t,u))},_toggle:function(t,i){function s(){a.running=!1,a._trigger("activate",t,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr("aria-hidden","true"),i.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr("aria-hidden","false"),i.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(t){var i,s=this._findActive(t);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return"string"==typeof e&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tablist.unbind(this.eventNamespace),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),i=t.data("ui-tabs-aria-controls");i?t.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(t){var i=this.options.disabled;i!==!1&&(void 0===t?i=!1:(t=this._getIndex(t),i=e.isArray(i)?e.map(i,function(e){return e!==t?e:null}):e.map(this.tabs,function(e,i){return i!==t?i:null})),this._setupDisabled(i))},disable:function(t){var i=this.options.disabled;if(i!==!0){if(void 0===t)i=!0;else{if(t=this._getIndex(t),-1!==e.inArray(t,i))return;i=e.isArray(i)?e.merge([t],i).sort():[t]}this._setupDisabled(i)}},load:function(t,i){t=this._getIndex(t);var s=this,n=this.tabs.eq(t),a=n.find(".ui-tabs-anchor"),o=this._getPanelForTab(n),r={tab:n,panel:o},h=function(e,t){"abort"===t&&s.panels.stop(!1,!0),n.removeClass("ui-tabs-loading"),o.removeAttr("aria-busy"),e===s.xhr&&delete s.xhr};this._isLocal(a[0])||(this.xhr=e.ajax(this._ajaxSettings(a,i,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(n.addClass("ui-tabs-loading"),o.attr("aria-busy","true"),this.xhr.done(function(e,t,n){setTimeout(function(){o.html(e),s._trigger("load",i,r),h(n,t)},1)}).fail(function(e,t){setTimeout(function(){h(e,t)},1)})))},_ajaxSettings:function(t,i,s){var n=this;return{url:t.attr("href"),beforeSend:function(t,a){return n._trigger("beforeLoad",i,e.extend({jqXHR:t,ajaxSettings:a},s))}}},_getPanelForTab:function(t){var i=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}}),e.widget("ui.tooltip",{version:"1.11.4",options:{content:function(){var t=e(this).attr("title")||"";return e("<a>").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_addDescribedBy:function(t,i){var s=(t.attr("aria-describedby")||"").split(/\s+/);s.push(i),t.data("ui-tooltip-id",i).attr("aria-describedby",e.trim(s.join(" ")))},_removeDescribedBy:function(t){var i=t.data("ui-tooltip-id"),s=(t.attr("aria-describedby")||"").split(/\s+/),n=e.inArray(i,s);-1!==n&&s.splice(n,1),t.removeData("ui-tooltip-id"),s=e.trim(s.join(" ")),s?t.attr("aria-describedby",s):t.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable(),this.liveRegion=e("<div>").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body)},_setOption:function(t,i){var s=this;return"disabled"===t?(this[i?"_disable":"_enable"](),this.options[t]=i,void 0):(this._super(t,i),"content"===t&&e.each(this.tooltips,function(e,t){s._updateContent(t.element)}),void 0)},_disable:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event("blur");n.target=n.currentTarget=s.element[0],t.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).removeAttr("title")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var i=this,s=e(t?t.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),t&&"mouseover"===t.type&&s.parents().each(function(){var t,s=e(this);s.data("ui-tooltip-open")&&(t=e.Event("blur"),t.target=t.currentTarget=this,i.close(t,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._registerCloseHandlers(t,s),this._updateContent(s,t))},_updateContent:function(e,t){var i,s=this.options.content,n=this,a=t?t.type:null;return"string"==typeof s?this._open(t,e,s):(i=s.call(e[0],function(i){n._delay(function(){e.data("ui-tooltip-open")&&(t&&(t.type=a),this._open(t,e,i))})}),i&&this._open(t,e,i),void 0)},_open:function(t,i,s){function n(e){l.of=e,o.is(":hidden")||o.position(l)}var a,o,r,h,l=e.extend({},this.options.position);if(s){if(a=this._find(i))return a.tooltip.find(".ui-tooltip-content").html(s),void 0;i.is("[title]")&&(t&&"mouseover"===t.type?i.attr("title",""):i.removeAttr("title")),a=this._tooltip(i),o=a.tooltip,this._addDescribedBy(i,o.attr("id")),o.find(".ui-tooltip-content").html(s),this.liveRegion.children().hide(),s.clone?(h=s.clone(),h.removeAttr("id").find("[id]").removeAttr("id")):h=s,e("<div>").html(h).appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:n}),n(t)):o.position(e.extend({of:i},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(r=this.delayedShow=setInterval(function(){o.is(":visible")&&(n(l.of),clearInterval(r))},e.fx.interval)),this._trigger("open",t,{tooltip:o})}},_registerCloseHandlers:function(t,i){var s={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var s=e.Event(t);s.currentTarget=i[0],this.close(s,!0)}}};i[0]!==this.element[0]&&(s.remove=function(){this._removeTooltip(this._find(i).tooltip)}),t&&"mouseover"!==t.type||(s.mouseleave="close"),t&&"focusin"!==t.type||(s.focusout="close"),this._on(!0,i,s)},close:function(t){var i,s=this,n=e(t?t.currentTarget:this.element),a=this._find(n);return a?(i=a.tooltip,a.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&!n.attr("title")&&n.attr("title",n.data("ui-tooltip-title")),this._removeDescribedBy(n),a.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(e(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),t&&"mouseleave"===t.type&&e.each(this.parents,function(t,i){e(i.element).attr("title",i.title),delete s.parents[t]}),a.closing=!0,this._trigger("close",t,{tooltip:i}),a.hiding||(a.closing=!1)),void 0):(n.removeData("ui-tooltip-open"),void 0)},_tooltip:function(t){var i=e("<div>").attr("role","tooltip").addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||"")),s=i.uniqueId().attr("id");return e("<div>").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),this.tooltips[s]={element:t,tooltip:i}},_find:function(e){var t=e.data("ui-tooltip-id");return t?this.tooltips[t]:null},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event("blur"),a=s.element;n.target=n.currentTarget=a[0],t.close(n,!0),e("#"+i).remove(),a.data("ui-tooltip-title")&&(a.attr("title")||a.attr("title",a.data("ui-tooltip-title")),a.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}})});
 
 
 
 
 
 
 
 
 
 
 
 
 
class-wcal-update.php CHANGED
@@ -20,6 +20,17 @@ if ( ! class_exists( 'Wcal_Update' ) ) {
20
  */
21
  class Wcal_Update {
22
 
 
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * It will be executed when the plugin is upgraded.
25
  *
@@ -31,7 +42,7 @@ if ( ! class_exists( 'Wcal_Update' ) ) {
31
 
32
  $wcal_previous_version = get_option( 'wcal_previous_version' );
33
 
34
- if( wcal_common::wcal_get_version() !== $wcal_previous_version ) {
35
  // check whether its a multi site install or a single site install.
36
  if ( is_multisite() ) {
37
 
@@ -54,7 +65,7 @@ if ( ! class_exists( 'Wcal_Update' ) ) {
54
  self::wcal_process_db_update();
55
  }
56
  }
57
-
58
  }
59
 
60
  /**
@@ -102,7 +113,7 @@ if ( ! class_exists( 'Wcal_Update' ) ) {
102
  */
103
  if ( $wpdb->get_var( "SHOW TABLES LIKE '{$db_prefix}ac_guest_abandoned_cart_history_lite';" ) && 'yes' !== $wcal_guest_user_id_altered ) { //phpcs:ignore
104
  $last_id = $wpdb->get_var( "SELECT max(id) FROM `{$db_prefix}ac_guest_abandoned_cart_history_lite`;" ); //phpcs:ignore
105
- if ( null != $last_id && $last_id <= 63000000 ) {
106
  $wpdb->query( "ALTER TABLE {$db_prefix}ac_guest_abandoned_cart_history_lite AUTO_INCREMENT = 63000000;" ); //phpcs:ignore
107
 
108
  if ( 0 === $blog_id ) {
@@ -232,8 +243,45 @@ if ( ! class_exists( 'Wcal_Update' ) ) {
232
  update_blog_option( $blog_id, 'ac_lite_alter_table_queries', 'yes' );
233
  }
234
  }
 
 
 
 
 
 
 
235
  }
236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  /**
238
  * Move settings from serialized to individual.
239
  *
20
  */
21
  class Wcal_Update {
22
 
23
+ /**
24
+ * Add a scheduled event for updating the DB for each version update.
25
+ *
26
+ * @since 5.8.2
27
+ */
28
+ public static function wcal_schedule_update_action() {
29
+ // IMP: The default value for get option should be updated in each release to match the current version to ensure update code is not run for first time installs.
30
+ if ( get_option( 'wcal_previous_version', '5.8.2' ) != WCAL_PLUGIN_VERSION && function_exists( 'as_enqueue_async_action' ) && false === as_next_scheduled_action( 'wcal_update_db' ) ) {
31
+ as_enqueue_async_action( 'wcal_update_db' );
32
+ }
33
+ }
34
  /**
35
  * It will be executed when the plugin is upgraded.
36
  *
42
 
43
  $wcal_previous_version = get_option( 'wcal_previous_version' );
44
 
45
+ if ( wcal_common::wcal_get_version() !== $wcal_previous_version ) {
46
  // check whether its a multi site install or a single site install.
47
  if ( is_multisite() ) {
48
 
65
  self::wcal_process_db_update();
66
  }
67
  }
68
+
69
  }
70
 
71
  /**
113
  */
114
  if ( $wpdb->get_var( "SHOW TABLES LIKE '{$db_prefix}ac_guest_abandoned_cart_history_lite';" ) && 'yes' !== $wcal_guest_user_id_altered ) { //phpcs:ignore
115
  $last_id = $wpdb->get_var( "SELECT max(id) FROM `{$db_prefix}ac_guest_abandoned_cart_history_lite`;" ); //phpcs:ignore
116
+ if ( null !== $last_id && $last_id <= 63000000 ) {
117
  $wpdb->query( "ALTER TABLE {$db_prefix}ac_guest_abandoned_cart_history_lite AUTO_INCREMENT = 63000000;" ); //phpcs:ignore
118
 
119
  if ( 0 === $blog_id ) {
243
  update_blog_option( $blog_id, 'ac_lite_alter_table_queries', 'yes' );
244
  }
245
  }
246
+
247
+ // 5.8.2 - Rename manual_email to email_reminder_status.
248
+ if ( 'yes' !== get_option( 'wcal_add_email_status_col', '' ) ) {
249
+ add_option( 'wcal_add_email_status_col', 'yes' );
250
+ self::wcal_update_email_status( $db_prefix );
251
+ }
252
+
253
  }
254
 
255
+ /**
256
+ * Add a new column email_reminder_status in the cart history lite table.
257
+ *
258
+ * @param string $db_prefix - DB prefix.
259
+ * @since 5.8.2
260
+ */
261
+ public static function wcal_update_email_status( $db_prefix ) {
262
+
263
+ global $wpdb;
264
+
265
+ if ( $wpdb->get_var( "SHOW TABLES LIKE '{$db_prefix}ac_abandoned_cart_history_lite';" ) ) { //phpcs:ignore
266
+ if ( ! $wpdb->get_var( "SHOW COLUMNS FROM `{$db_prefix}ac_abandoned_cart_history_lite` LIKE 'email_reminder_status';" ) ) { //phpcs:ignore
267
+ $wpdb->query( "ALTER TABLE {$db_prefix}ac_abandoned_cart_history_lite ADD `email_reminder_status` VARCHAR(50) COLLATE utf8_unicode_ci NOT NULL AFTER `session_id`;" ); //phpcs:ignore
268
+ }
269
+ }
270
+
271
+ // Mark the old carts for whom email sequences have completed as 'complete'.
272
+ $get_last_template = wcal_common::wcal_get_last_email_template();
273
+ $template_freq = is_array( $get_last_template ) ? intval( array_pop( $get_last_template ) ) : 0;
274
+ $cron_duration = 15 * 60;
275
+ $leave_carts_abandoned_in = current_time( 'timestamp' ) - ( $template_freq + $cron_duration ); // phpcs:ignore
276
+
277
+ $wpdb->query( // phpcs:ignore
278
+ $wpdb->prepare(
279
+ 'UPDATE ' . $db_prefix . "ac_abandoned_cart_history_lite SET email_reminder_status = 'complete' WHERE abandoned_cart_time < %s AND email_reminder_status = ''", // phpcs:ignore
280
+ $leave_carts_abandoned_in
281
+ )
282
+ );
283
+
284
+ }
285
  /**
286
  * Move settings from serialized to individual.
287
  *
cron/wcal_send_email.php CHANGED
@@ -12,16 +12,12 @@ if ( ! isset( $wp_load ) ) {
12
  $wp_load = false;
13
  $dir = __FILE__;
14
  while ( '/' != ( $dir = dirname( $dir ) ) ) {
15
- /**
16
- * Comment this "If" condition for generating the developer documentations.
17
- */
18
  if ( file_exists( $wp_load = "{$dir}/wp-load.php" ) ) {
19
  break;
20
  }
21
  }
22
- /*
23
- * In case wp-content folder is seperated from WP core folders (like Bedrock setup from Roots.io) the above while loop will not find wp-load correctly, so we must use ABSPATH
24
- */
25
  if ( ! file_exists( $wp_load ) ) {
26
  $wp_load = trailingslashit( ABSPATH ) . 'wp-load.php';
27
  }
@@ -50,32 +46,41 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
50
  * @globals mixed $woocommerce
51
  * @since 1.3
52
  */
53
- function wcal_send_email_notification() {
54
  global $wpdb, $woocommerce;
55
 
56
- if ( 'on' == get_option( 'wcal_enable_cart_emails' ) ) {
57
  // Grab the cart abandoned cut-off time from database.
58
- $cart_settings = get_option( 'ac_lite_cart_abandoned_time' );
59
 
60
- if ( $cart_settings == '' ) {
61
  $cart_settings = 10;
62
  }
63
 
64
  $cart_abandon_cut_off_time = $cart_settings * 60;
65
- // Fetch all active templates present in the system
66
- $query = 'SELECT wpet . * FROM `' . $wpdb->prefix . "ac_email_templates_lite` AS wpet
67
- WHERE wpet.is_active = '1' ORDER BY `day_or_hour` DESC, `frequency` ASC ";
68
- $results = $wpdb->get_results( $query );
69
  $hour_seconds = 3600; // 60 * 60
70
  $day_seconds = 86400; // 24 * 60 * 60
 
 
 
 
 
 
 
 
 
 
71
  foreach ( $results as $key => $value ) {
72
- if ( $value->day_or_hour == 'Days' ) {
73
  $time_to_send_template_after = intval( $value->frequency ) * $day_seconds;
74
- } elseif ( $value->day_or_hour == 'Hours' ) {
75
  $time_to_send_template_after = intval( $value->frequency ) * $hour_seconds;
76
  }
 
77
 
78
- $carts = $this->wcal_get_carts( $time_to_send_template_after, $cart_abandon_cut_off_time, $value->id );
79
  $email_frequency = $value->frequency;
80
  $email_body_template = $value->body;
81
  $template_email_subject = stripslashes( $value->subject );
@@ -94,19 +99,23 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
94
  }
95
  $template_id = $value->id;
96
  $is_wc_template = $value->is_wc_template;
97
- $wc_template_header_text = $value->wc_email_header != '' ? $value->wc_email_header : __( 'Abandoned cart reminder', 'woocommerce-abandoned-cart' );
98
  $wc_template_header = stripslashes( $wc_template_header_text );
99
- if ( '' != $email_body_template ) {
100
  foreach ( $carts as $key => $value ) {
101
 
102
  $wcal_is_guest_id_correct = $this->wcal_get_is_guest_valid( $value->user_id, $value->user_type );
103
  if ( true === $wcal_is_guest_id_correct ) {
104
 
105
- if ( $value->user_type == 'GUEST' && $value->user_id != '0' ) {
106
  $value->user_login = '';
107
- $query_guest = 'SELECT billing_first_name, billing_last_name, email_id FROM `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite`
108
- WHERE id = %d';
109
- $results_guest = $wpdb->get_results( $wpdb->prepare( $query_guest, $value->user_id ) );
 
 
 
 
110
  if ( count( $results_guest ) > 0 && isset( $results_guest[0]->email_id ) && '' !== $results_guest[0]->email_id ) {
111
  $value->user_email = $results_guest[0]->email_id;
112
  } else {
@@ -118,9 +127,9 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
118
  }
119
  $key = 'billing_email';
120
  $single = true;
121
- $user_biiling_email = get_user_meta( $user_id, $key, $single );
122
- if ( isset( $user_biiling_email ) && $user_biiling_email != '' ) {
123
- $value->user_email = $user_biiling_email;
124
  }
125
  }
126
  if ( isset( $value->abandoned_cart_info ) ) {
@@ -130,10 +139,10 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
130
  if ( ! empty( $cart_info_db_field->cart ) ) {
131
  $cart = $cart_info_db_field->cart;
132
  }
133
- if ( count( get_object_vars( $cart ) ) > 0 && isset( $value->user_id ) && '0' != $value->user_id && isset( $value->id ) ) {
134
  $cart_update_time = $value->abandoned_cart_time;
135
  $new_user = $this->wcal_check_sent_history( $value->user_id, $cart_update_time, $template_id, $value->id );
136
- if ( $new_user == true ) {
137
 
138
  /**
139
  * When there are 3 templates and for cart id 1 all template time has been reached. BUt all templates
@@ -142,7 +151,6 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
142
  * So below function check that after first email is sent time and then from that time it will send the
143
  * 2nd template time. ( It will not consider the cart abadoned time in this case. )
144
  */
145
-
146
  $wcal_check_cart_needed_for_multiple_template = $this->wcal_remove_cart_for_mutiple_templates( $value->id, $time_to_send_template_after, $template_id );
147
 
148
  /**
@@ -154,35 +162,48 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
154
  * condition will not call that function andthe reminder email will be sent.
155
  */
156
 
157
- $wcal_check_if_cart_is_present_in_post_meta = 'SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `' . $wpdb->prefix . 'postmeta` AS wpm
158
- LEFT JOIN `' . $wpdb->prefix . "posts` AS wpost
159
- ON wpm.post_id = wpost.ID
160
- WHERE wpm.meta_key = 'wcal_recover_order_placed' AND
161
- wpm.meta_value = %s AND wpm.post_id = wpost.ID AND
162
- wpost.post_type = 'shop_order'
163
- ORDER BY wpm.post_id DESC LIMIT 1";
164
-
165
- $results_wcal_check_if_cart_is_present_in_post_meta = $wpdb->get_results( $wpdb->prepare( $wcal_check_if_cart_is_present_in_post_meta, $value->id ) );
 
 
 
166
 
167
  $wcap_check_cart_staus_need_to_update = false;
168
 
 
169
  if ( empty( $results_wcal_check_if_cart_is_present_in_post_meta ) ||
170
  ( isset( $results_wcal_check_if_cart_is_present_in_post_meta[0] ) &&
171
- $results_wcal_check_if_cart_is_present_in_post_meta[0]->post_status != 'wc-failed' &&
172
- $results_wcal_check_if_cart_is_present_in_post_meta [0]->post_status != 'wc-pending' ) ) {
173
-
174
  $wcap_check_cart_staus_need_to_update = self::wcal_update_abandoned_cart_status_for_placed_orders( $time_to_send_template_after, $cart_update_time, $value->user_id, $value->user_type, $value->id, $value->user_email );
175
  }
176
 
177
- if ( false == $wcal_check_cart_needed_for_multiple_template &&
178
- false == $wcap_check_cart_staus_need_to_update ) {
 
 
 
 
 
 
 
 
 
 
 
179
 
180
  $cart_info_db = $value->abandoned_cart_info;
181
  $email_subject = $template_email_subject;
182
  $email_body = $email_body_template;
183
  $wcal_check_cart_total = $this->wcal_check_cart_total( $cart );
184
- if ( true == $wcal_check_cart_total ) {
185
- if ( $value->user_type == 'GUEST' ) {
186
  if ( isset( $results_guest[0]->billing_first_name ) ) {
187
  $email_body = str_ireplace( '{{customer.firstname}}', $results_guest[0]->billing_first_name, $email_body );
188
  $email_subject = str_ireplace( '{{customer.firstname}}', $results_guest[0]->billing_first_name, $email_subject );
@@ -200,7 +221,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
200
  } else {
201
  $user_first_name = '';
202
  $user_first_name_temp = get_user_meta( $value->user_id, 'billing_first_name', true );
203
- if ( isset( $user_first_name_temp ) && '' == $user_first_name_temp ) {
204
  $user_data = get_userdata( $user_id );
205
  if ( isset( $user_data->first_name ) ) {
206
  $user_first_name = $user_data->first_name;
@@ -214,7 +235,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
214
  $email_subject = str_ireplace( '{{customer.firstname}}', $user_first_name, $email_subject );
215
  $user_last_name = '';
216
  $user_last_name_temp = get_user_meta( $value->user_id, 'billing_last_name', true );
217
- if ( isset( $user_last_name_temp ) && '' == $user_last_name_temp ) {
218
  $user_data = get_userdata( $user_id );
219
  if ( isset( $user_data->last_name ) ) {
220
  $user_last_name = $user_data->last_name;
@@ -228,29 +249,36 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
228
  $email_body = str_ireplace( '{{customer.fullname}}', $user_first_name . ' ' . $user_last_name, $email_body );
229
  }
230
  $order_date = '';
231
- if ( $cart_update_time != '' && $cart_update_time != 0 ) {
232
  $date_format = date_i18n( get_option( 'date_format' ), $cart_update_time );
233
  $time_format = date_i18n( get_option( 'time_format' ), $cart_update_time );
234
  $order_date = $date_format . ' ' . $time_format;
235
  }
236
  $email_body = str_ireplace( '{{cart.abandoned_date}}', $order_date, $email_body );
237
- $query_sent = 'INSERT INTO `' . $wpdb->prefix . "ac_sent_history_lite` ( template_id, abandoned_order_id, sent_time, sent_email_id )
238
- VALUES ( %s, %s, '" . current_time( 'mysql' ) . "', %s )";
239
 
240
- $wpdb->query( $wpdb->prepare( $query_sent, $template_id, $value->id, $value->user_email ) );
241
-
242
- $query_id = 'SELECT * FROM `' . $wpdb->prefix . 'ac_sent_history_lite`
243
- WHERE template_id = %s AND abandoned_order_id = %s
244
- ORDER BY id DESC
245
- LIMIT 1 ';
246
- $results_sent = $wpdb->get_results( $wpdb->prepare( $query_id, $template_id, $value->id ) );
 
 
 
 
 
 
 
 
 
247
  if ( count( $results_sent ) > 0 ) {
248
  $email_sent_id = $results_sent[0]->id;
249
  } else {
250
  $email_sent_id = '';
251
  }
252
 
253
- if ( '' != $email_sent_id ) {
254
 
255
  if ( $woocommerce->version < '2.3' ) {
256
  $cart_page_link = $woocommerce->cart->get_cart_url();
@@ -300,7 +328,9 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
300
  </tr>';
301
  }
302
  $cart_details = $cart_info_db_field->cart;
303
- $cart_total = $item_subtotal = $item_total = 0;
 
 
304
  $sub_line_prod_name = '';
305
  foreach ( $cart_details as $k => $v ) {
306
  $quantity_total = $v->quantity;
@@ -310,27 +340,27 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
310
  $prod_name = get_post( $product_id );
311
  $product_link_track = get_permalink( $product_id );
312
  $product_name = $prod_name->post_title;
313
- if ( $sub_line_prod_name == '' ) {
314
  $sub_line_prod_name = $product_name;
315
  }
316
- // Item subtotal is calculated as product total including taxes
317
- if ( $v->line_tax != 0 && $v->line_tax > 0 ) {
318
  $item_subtotal = $item_subtotal + $v->line_total + $v->line_tax;
319
  } else {
320
  $item_subtotal = $item_subtotal + $v->line_total;
321
  }
322
- // Line total
323
  $item_total = $item_subtotal;
324
  $item_subtotal = $item_subtotal / $quantity_total;
325
  $item_total_display = wc_price( $item_total );
326
  $item_subtotal = wc_price( $item_subtotal );
327
- // $product = wc_get_product( $product_id );
328
  $prod_image = $product->get_image();
329
  $image_url = wp_get_attachment_url( get_post_thumbnail_id( $product_id ) );
330
  if ( strpos( $image_url, '/' ) === 0 ) {
331
  $image_url = get_option( 'siteurl' ) . $image_url;
332
  }
333
- if ( isset( $v->variation_id ) && '' != $v->variation_id ) {
334
  $variation_id = $v->variation_id;
335
  $variation = wc_get_product( $variation_id );
336
  $name = false !== $variation ? $variation->get_formatted_name() : '';
@@ -373,13 +403,14 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
373
  <td> ' . apply_filters( 'wcal_reminder_email_line_subtotal_value', $item_total_display ) . '</td>
374
  </tr>';
375
  $cart_total += $item_total;
376
- $item_subtotal = $item_total = 0;
 
377
  $p_exists = true;
378
  } else {
379
  $cart_total = 0;
380
- $item_subtotal = $item_total = 0;
381
-
382
- $p_exists = false;
383
  }
384
  }
385
 
@@ -406,7 +437,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
406
  $user_email = $value->user_email;
407
  $email_body_final = stripslashes( $email_body );
408
  $email_body_final = convert_smilies( $email_body_final );
409
- if ( isset( $is_wc_template ) && '1' == $is_wc_template ) {
410
  ob_start();
411
 
412
  wc_get_template( 'emails/email-header.php', array( 'email_heading' => $wc_template_header ) );
@@ -443,54 +474,54 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
443
  * This function will check if the user type is Guest and the id is greater than 63000000
444
  * Then conider that as a correct guest user, if is not then do not send the emails
445
  *
446
- * @param strinng | int $wcal_user_id User id
447
- * @param strinng $wcal_user_type User Type
448
- * @return boolean true | false
449
  * @since 4.4
450
  */
451
  public static function wcal_get_is_guest_valid( $wcal_user_id, $wcal_user_type ) {
452
 
453
- if ( 'REGISTERED' == $wcal_user_type ) {
454
  return true;
455
  }
456
 
457
- if ( 'GUEST' == $wcal_user_type && $wcal_user_id >= 63000000 ) {
458
  return true;
459
  }
460
 
461
- /**
462
- * It indicates that the user type is guest but the id for them is wrong.
463
- */
464
  return false;
465
  }
466
 
467
  /**
468
  * It will check the cart total.
469
  *
470
- * @param array | object $cart Cart details
471
  * @return boolean true | false
472
  * @since 4.3
473
  */
474
- function wcal_check_cart_total( $cart ) {
475
  foreach ( $cart as $k => $v ) {
476
- if ( $v->line_total != 0 && $v->line_total > 0 ) {
477
  return true;
478
  }
479
  }
480
  return false;
481
  }
 
482
  /**
483
  * Get all carts which have the creation time earlier than the one that is passed.
484
  *
485
- * @param string | timestamp $template_to_send_after_time Template time
486
- * @param string | timestamp $cart_abandon_cut_off_time Cutoff time
 
487
  * @globals mixed $wpdb
488
  * @return array | object $results
489
  * @since 1.3
490
  */
491
- function wcal_get_carts( $template_to_send_after_time, $cart_abandon_cut_off_time, $template_id ) {
492
  global $wpdb;
493
- $cart_time = current_time( 'timestamp' ) - $template_to_send_after_time - $cart_abandon_cut_off_time;
494
 
495
  $wcal_template_time = get_option( 'wcal_template_' . $template_id . '_time' );
496
  $wcal_add_template_condition = '';
@@ -499,27 +530,33 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
499
  }
500
  $cart_ignored = 0;
501
  $unsubscribe = 0;
502
- $query = 'SELECT wpac . * , wpu.user_login, wpu.user_email
503
- FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` AS wpac
504
- LEFT JOIN ' . $wpdb->base_prefix . "users AS wpu ON wpac.user_id = wpu.id
505
- WHERE cart_ignored = %s AND unsubscribe_link = %s AND abandoned_cart_time < $cart_time
506
- $wcal_add_template_condition
507
- ORDER BY `id` ASC ";
508
-
509
- $results = $wpdb->get_results( $wpdb->prepare( $query, $cart_ignored, $unsubscribe ) );
 
 
 
 
 
 
 
510
  return $results;
511
- exit;
512
  }
513
 
514
  /**
515
  * It will update the abandoned cart staus if the order has been placed before sending the reminder emails.
516
  *
517
- * @param string | timestamp $time_to_send_template_after Template time
518
- * @param string | timestamp $wcal_cart_time Abandoned time
519
- * @param string | int $wcal_user_id User id
520
- * @param string $wcal_user_type User type
521
- * @param string | int $wcal_cart_id Abandoned cart id
522
- * @param string $wcal_user_email User Email
523
  * @globals mixed $wpdb
524
  * @return boolean true | false
525
  * @since 4.3
@@ -527,14 +564,14 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
527
  public static function wcal_update_abandoned_cart_status_for_placed_orders( $time_to_send_template_after, $wcal_cart_time, $wcal_user_id, $wcal_user_type, $wcal_cart_id, $wcal_user_email ) {
528
  global $wpdb;
529
 
530
- if ( $wcal_user_id >= '63000000' && 'GUEST' == $wcal_user_type ) {
531
  $updated_value = self::wcal_update_status_of_guest( $wcal_cart_id, $wcal_cart_time, $time_to_send_template_after, $wcal_user_email );
532
- if ( 1 == $updated_value ) {
533
  return true;
534
  }
535
- } elseif ( $wcal_user_id < '63000000' && 'REGISTERED' == $wcal_user_type ) {
536
  $updated_value = self::wcal_update_status_of_loggedin( $wcal_cart_id, $wcal_cart_time, $time_to_send_template_after, $wcal_user_email );
537
- if ( 1 == $updated_value ) {
538
  return true;
539
  }
540
  }
@@ -544,43 +581,47 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
544
  /**
545
  * It will update the Guest users abandoned cart staus if the order has been placed before sending the reminder emails.
546
  *
547
- * @param string | int $cart_id Abandoned cart id
548
- * @param string | timestamp $time_to_send_template_after Template time
549
- * @param string | timestamp $abandoned_cart_time Abandoned time
550
- * @param string $wcal_user_email_address User Email
551
  * @globals mixed $wpdb
552
- * @return int 0 | 1
553
  * @since 4.3
554
  */
555
  public static function wcal_update_status_of_guest( $cart_id, $abandoned_cart_time, $time_to_send_template_after, $wcal_user_email_address ) {
556
  global $wpdb;
557
 
558
- $query_email_id = 'SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `' . $wpdb->prefix . 'postmeta` AS wpm LEFT JOIN `' . $wpdb->prefix . "posts` AS wpost ON wpm.post_id = wpost.ID
559
- WHERE wpm.meta_key = '_billing_email' AND wpm.meta_value = %s AND wpm.post_id = wpost.ID AND wpost.post_type = 'shop_order' Order BY wpm.post_id DESC LIMIT 1";
 
 
 
 
 
560
 
561
- $results_query_email = $wpdb->get_results( $wpdb->prepare( $query_email_id, $wcal_user_email_address ) );
562
-
563
- /* This will check that For abc@abc.com email address we have order for todays date in WC post table */
564
  if ( count( $results_query_email ) > 0 ) {
565
 
566
- $current_time = current_time( 'timestamp' );
567
- $todays_date = date( 'Y-m-d', $current_time );
568
 
569
  $order_date_with_time = $results_query_email[0]->post_date;
570
  $order_date = substr( $order_date_with_time, 0, 10 );
571
 
572
- if ( $order_date == $todays_date ) {
573
 
574
- /**
575
- * in some case the cart is recovered but it is not marked as the recovered. So here we check if any
576
- * record is found for that cart id if yes then update the record respectively.
577
- */
578
  $wcal_check_email_sent_to_cart = self::wcal_get_cart_sent_data( $cart_id );
579
 
580
- if ( 0 != $wcal_check_email_sent_to_cart ) {
581
 
582
- $wcal_query = 'SELECT `post_id` FROM `' . $wpdb->prefix . 'postmeta` WHERE meta_value = %s';
583
- $wcal_results = $wpdb->get_results( $wpdb->prepare( $wcal_query, $cart_id ) );
 
 
 
 
584
 
585
  if ( count( $wcal_results ) > 0 ) {
586
 
@@ -588,8 +629,13 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
588
 
589
  $order = wc_get_order( $order_id );
590
 
591
- $query_order = 'UPDATE `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET recovered_cart= %s, cart_ignored = '1' WHERE id = %s";
592
- $wpdb->query( $wpdb->prepare( $query_order, $order_id, $cart_id ) );
 
 
 
 
 
593
 
594
  $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-abandoned-cart' ) );
595
 
@@ -597,20 +643,24 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
597
  delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', $wcal_check_email_sent_to_cart );
598
  }
599
  } else {
600
-
601
- $query_ignored = 'UPDATE `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id = %s";
602
- $wpdb->query( $wpdb->prepare( $query_ignored, $cart_id ) );
 
 
 
603
  }
604
  return 1;
605
  } elseif ( strtotime( $order_date_with_time ) > $abandoned_cart_time ) {
606
- $query_ignored = 'UPDATE `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id = %s ";
607
- $wpdb->query( $wpdb->prepare( $query_ignored, $cart_id ) );
 
 
 
 
608
  return 1;
609
- } elseif ( 'wc-pending' == $results_query_email[0]->post_status || 'wc-failed' == $results_query_email[0]->post_status ) {
610
-
611
- /**
612
- * If the post status are pending or failed the send them for abandoned cart reminder emails.
613
- */
614
  return 0;
615
  }
616
  }
@@ -620,35 +670,42 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
620
  /**
621
  * It will update the Loggedin users abandoned cart staus if the order has been placed before sending the reminder emails.
622
  *
623
- * @param string | int $cart_id Abandoned cart id
624
- * @param string | timestamp $time_to_send_template_after Template time
625
- * @param string | timestamp $abandoned_cart_time Abandoned time
626
- * @param string $user_billing_email User Email
627
  * @globals mixed $wpdb
628
- * @return int 0 | 1
629
  * @since 4.3
630
  */
631
  public static function wcal_update_status_of_loggedin( $cart_id, $abandoned_cart_time, $time_to_send_template_after, $user_billing_email ) {
632
  global $wpdb;
633
 
634
- $query_email_id = 'SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `' . $wpdb->prefix . 'postmeta` AS wpm LEFT JOIN `' . $wpdb->prefix . "posts` AS wpost ON wpm.post_id = wpost.ID WHERE wpm.meta_key = '_billing_email' AND wpm.meta_value = %s AND wpm.post_id = wpost.ID Order BY wpm.post_id DESC LIMIT 1";
635
-
636
- $results_query_email = $wpdb->get_results( $wpdb->prepare( $query_email_id, $user_billing_email ) );
 
 
 
637
 
638
  if ( count( $results_query_email ) > 0 ) {
639
- $current_time = current_time( 'timestamp' );
640
- $todays_date = date( 'Y-m-d', $current_time );
641
  $order_date_time = $results_query_email[0]->post_date;
642
  $order_date = substr( $order_date_time, 0, 10 );
643
 
644
- if ( $order_date == $todays_date ) {
645
 
646
  $wcal_check_email_sent_to_cart = self::wcal_get_cart_sent_data( $cart_id );
647
 
648
- if ( 0 != $wcal_check_email_sent_to_cart ) {
649
 
650
- $wcal_query = 'SELECT `post_id` FROM `' . $wpdb->prefix . 'postmeta` WHERE meta_value = %s';
651
- $wcal_results = $wpdb->get_results( $wpdb->prepare( $wcal_query, $cart_id ) );
 
 
 
 
652
 
653
  if ( count( $wcal_results ) > 0 ) {
654
 
@@ -656,8 +713,9 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
656
 
657
  $order = wc_get_order( $order_id );
658
 
659
- $query_order = 'UPDATE `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET recovered_cart= '" . $order_id . "', cart_ignored = '1' WHERE id = '" . $cart_id . "' ";
660
- $wpdb->query( $query_order );
 
661
 
662
  $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-abandoned-cart' ) );
663
 
@@ -665,17 +723,18 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
665
  delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', $wcal_check_email_sent_to_cart );
666
  }
667
  } else {
668
-
669
- $query_ignored = 'UPDATE `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
670
- $wpdb->query( $query_ignored );
671
  }
672
  return 1;
673
  } elseif ( strtotime( $order_date_time ) >= $abandoned_cart_time ) {
674
- $query_ignored = 'UPDATE `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'";
675
- $wpdb->query( $query_ignored );
 
676
  return 1; // We return here 1 so it indicate that the cart has been modifed so do not sent email and delete from the array.
677
- } elseif ( 'wc-pending' == $results_query_email[0]->post_status || 'wc-failed' == $results_query_email[0]->post_status ) {
678
- return 0; // if status of the order is pending or falied then return 0 so it will not delete that cart and send reminder email
679
  }
680
  }
681
  return 0; // it means there are no record found to be update it.
@@ -684,16 +743,20 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
684
  /**
685
  * It will check that for abandoned cart remider email has been sent.
686
  *
687
- * @param string | int $wcal_cart_id Abandoned cart id
688
- * @return int $wcal_sent_id | 0 Email sent id
689
  * @globals mixed $wpdb
690
  * @since 4.3
691
  */
692
  public static function wcal_get_cart_sent_data( $wcal_cart_id ) {
693
  global $wpdb;
694
 
695
- $wcal_query = 'SELECT id FROM `' . $wpdb->prefix . "ac_sent_history_lite` WHERE abandoned_order_id = %d ORDER BY 'id' DESC LIMIT 1 ";
696
- $wcal_results = $wpdb->get_results( $wpdb->prepare( $wcal_query, $wcal_cart_id ) );
 
 
 
 
697
 
698
  if ( count( $wcal_results ) > 0 ) {
699
  $wcal_sent_id = $wcal_results[0]->id;
@@ -706,9 +769,9 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
706
  * If none of the email has been sent for some time then from the time where it send the first email template it will consider
707
  * the time and further email will sent from first email sent time. So all template will not sent at the same time.
708
  *
709
- * @param string | int $wcal_cart_id Abandoned cart id
710
- * @param string | timestamp $time_to_send_template_after Template time
711
- * @param string | int $template_id Template id
712
  * @return boolean true | false
713
  * @globals mixed $wpdb
714
  * @since 3.1
@@ -716,13 +779,14 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
716
  public static function wcal_remove_cart_for_mutiple_templates( $wcal_cart_id, $time_to_send_template_after, $template_id ) {
717
  global $wpdb;
718
 
719
- $wcal_get_last_email_sent_time = 'SELECT * FROM `' . $wpdb->prefix . "ac_sent_history_lite` WHERE abandoned_order_id = $wcal_cart_id ORDER BY `sent_time` DESC LIMIT 1";
720
- $wcal_get_last_email_sent_time_results_list = $wpdb->get_results( $wcal_get_last_email_sent_time );
 
721
 
722
  if ( count( $wcal_get_last_email_sent_time_results_list ) > 0 ) {
723
  $last_template_send_time = strtotime( $wcal_get_last_email_sent_time_results_list[0]->sent_time );
724
  $second_template_send_time = $last_template_send_time + $time_to_send_template_after;
725
- $current_time_test = current_time( 'timestamp' );
726
  if ( $second_template_send_time > $current_time_test ) {
727
  return true;
728
  }
@@ -733,35 +797,38 @@ if ( ! class_exists( 'woocommerce_abandon_cart_cron' ) ) {
733
  /**
734
  * This function is used to encode the validate string.
735
  *
736
- * @param string $validate
737
- * @return encoded data $validate_encoded
738
  * @since 1.3
739
  */
740
- function wcal_encrypt_validate( $validate ) {
741
- $cryptKey = get_option( 'wcal_security_key' );
742
- $validate_encoded = Wcal_Aes_Ctr::encrypt( $validate, $cryptKey, 256 );
743
  return( $validate_encoded );
744
  }
745
 
746
  /**
747
  * It will check if the reminder email has been sent to the abandoned cart.
748
  *
749
- * @param string | int $user_id User id
750
- * @param string | timestamp $cart_update_time Abandoned cart time
751
- * @param string | int $template_id Template id
752
- * @param string | int $id Abandoned cart id
753
  * @globals mixed $wpdb
754
- * @return boolean true | false
755
  * @since 1.3
756
  */
757
- function wcal_check_sent_history( $user_id, $cart_update_time, $template_id, $id ) {
758
  global $wpdb;
759
- $query = 'SELECT wpcs . * , wpac . abandoned_cart_time , wpac . user_id FROM `' . $wpdb->prefix . 'ac_sent_history_lite` AS wpcs
760
- LEFT JOIN ' . $wpdb->prefix . "ac_abandoned_cart_history_lite AS wpac ON wpcs.abandoned_order_id = wpac.id
761
- WHERE template_id = %s AND wpcs.abandoned_order_id = %d ORDER BY 'id' DESC LIMIT 1 ";
762
 
763
- $results = $wpdb->get_results( $wpdb->prepare( $query, $template_id, $id ) );
764
- if ( count( $results ) == 0 ) {
 
 
 
 
 
 
765
  return true;
766
  } elseif ( $results[0]->abandoned_cart_time < $cart_update_time ) {
767
  return true;
12
  $wp_load = false;
13
  $dir = __FILE__;
14
  while ( '/' != ( $dir = dirname( $dir ) ) ) {
15
+ // Comment this "If" condition for generating the developer documentations.
 
 
16
  if ( file_exists( $wp_load = "{$dir}/wp-load.php" ) ) {
17
  break;
18
  }
19
  }
20
+ // In case wp-content folder is seperated from WP core folders (like Bedrock setup from Roots.io) the above while loop will not find wp-load correctly, so we must use ABSPATH
 
 
21
  if ( ! file_exists( $wp_load ) ) {
22
  $wp_load = trailingslashit( ABSPATH ) . 'wp-load.php';
23
  }
46
  * @globals mixed $woocommerce
47
  * @since 1.3
48
  */
49
+ public function wcal_send_email_notification() {
50
  global $wpdb, $woocommerce;
51
 
52
+ if ( 'on' === get_option( 'wcal_enable_cart_emails', '' ) ) {
53
  // Grab the cart abandoned cut-off time from database.
54
+ $cart_settings = get_option( 'ac_lite_cart_abandoned_time', 10 );
55
 
56
+ if ( '' === $cart_settings ) {
57
  $cart_settings = 10;
58
  }
59
 
60
  $cart_abandon_cut_off_time = $cart_settings * 60;
61
+ // Fetch all active templates present in the system.
62
+ $query = "SELECT wpet . * FROM `" . $wpdb->prefix . "ac_email_templates_lite` AS wpet WHERE wpet.is_active = '1' ORDER BY `day_or_hour` DESC, `frequency` ASC"; // phpcs:ignore
63
+ $results = $wpdb->get_results( $query ); // phpcs:ignore
 
64
  $hour_seconds = 3600; // 60 * 60
65
  $day_seconds = 86400; // 24 * 60 * 60
66
+
67
+ // Find the template which is last in the sequence.
68
+ $last_email_template = wcal_common::wcal_get_last_email_template();
69
+ if ( is_array( $last_email_template ) && count( $last_email_template ) > 0 ) {
70
+ reset( $last_email_template );
71
+ $last_template_id = key( $last_email_template );
72
+ } else {
73
+ $last_template_id = 0;
74
+ }
75
+
76
  foreach ( $results as $key => $value ) {
77
+ if ( 'Days' === $value->day_or_hour ) {
78
  $time_to_send_template_after = intval( $value->frequency ) * $day_seconds;
79
+ } elseif ( 'Hours' === $value->day_or_hour ) {
80
  $time_to_send_template_after = intval( $value->frequency ) * $hour_seconds;
81
  }
82
+ $carts = $this->wcal_get_carts( $time_to_send_template_after, $cart_abandon_cut_off_time, $value->id );
83
 
 
84
  $email_frequency = $value->frequency;
85
  $email_body_template = $value->body;
86
  $template_email_subject = stripslashes( $value->subject );
99
  }
100
  $template_id = $value->id;
101
  $is_wc_template = $value->is_wc_template;
102
+ $wc_template_header_text = '' !== $value->wc_email_header ? $value->wc_email_header : __( 'Abandoned cart reminder', 'woocommerce-abandoned-cart' );
103
  $wc_template_header = stripslashes( $wc_template_header_text );
104
+ if ( '' !== $email_body_template ) {
105
  foreach ( $carts as $key => $value ) {
106
 
107
  $wcal_is_guest_id_correct = $this->wcal_get_is_guest_valid( $value->user_id, $value->user_type );
108
  if ( true === $wcal_is_guest_id_correct ) {
109
 
110
+ if ( 'GUEST' === $value->user_type && $value->user_id > 0 ) {
111
  $value->user_login = '';
112
+
113
+ $results_guest = $wpdb->get_results( // phpcs:ignore
114
+ $wpdb->prepare(
115
+ 'SELECT billing_first_name, billing_last_name, email_id FROM `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite` WHERE id = %d',
116
+ $value->user_id
117
+ )
118
+ );
119
  if ( count( $results_guest ) > 0 && isset( $results_guest[0]->email_id ) && '' !== $results_guest[0]->email_id ) {
120
  $value->user_email = $results_guest[0]->email_id;
121
  } else {
127
  }
128
  $key = 'billing_email';
129
  $single = true;
130
+ $user_billing_email = get_user_meta( $user_id, $key, $single );
131
+ if ( isset( $user_billing_email ) && '' !== $user_billing_email ) {
132
+ $value->user_email = $user_billing_email;
133
  }
134
  }
135
  if ( isset( $value->abandoned_cart_info ) ) {
139
  if ( ! empty( $cart_info_db_field->cart ) ) {
140
  $cart = $cart_info_db_field->cart;
141
  }
142
+ if ( count( get_object_vars( $cart ) ) > 0 && isset( $value->user_id ) && $value->user_id > 0 && isset( $value->id ) ) {
143
  $cart_update_time = $value->abandoned_cart_time;
144
  $new_user = $this->wcal_check_sent_history( $value->user_id, $cart_update_time, $template_id, $value->id );
145
+ if ( true === $new_user ) {
146
 
147
  /**
148
  * When there are 3 templates and for cart id 1 all template time has been reached. BUt all templates
151
  * So below function check that after first email is sent time and then from that time it will send the
152
  * 2nd template time. ( It will not consider the cart abadoned time in this case. )
153
  */
 
154
  $wcal_check_cart_needed_for_multiple_template = $this->wcal_remove_cart_for_mutiple_templates( $value->id, $time_to_send_template_after, $template_id );
155
 
156
  /**
162
  * condition will not call that function andthe reminder email will be sent.
163
  */
164
 
165
+ $results_wcal_check_if_cart_is_present_in_post_meta = $wpdb->get_results( // phpcs:ignore
166
+ $wpdb->prepare(
167
+ "SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `" . $wpdb->prefix . "postmeta` AS wpm
168
+ LEFT JOIN `" . $wpdb->prefix . "posts` AS wpost
169
+ ON wpm.post_id = wpost.ID
170
+ WHERE wpm.meta_key = 'wcal_recover_order_placed' AND
171
+ wpm.meta_value = %s AND wpm.post_id = wpost.ID AND
172
+ wpost.post_type = 'shop_order'
173
+ ORDER BY wpm.post_id DESC LIMIT 1",
174
+ $value->id
175
+ )
176
+ );
177
 
178
  $wcap_check_cart_staus_need_to_update = false;
179
 
180
+ $wc_order_status = isset( $results_wcal_check_if_cart_is_present_in_post_meta[0]->post_status ) ? $results_wcal_check_if_cart_is_present_in_post_meta[0]->post_status : '';
181
  if ( empty( $results_wcal_check_if_cart_is_present_in_post_meta ) ||
182
  ( isset( $results_wcal_check_if_cart_is_present_in_post_meta[0] ) &&
183
+ 'wc-failed' !== $wc_order_status && 'wc-pending' !== $wc_order_status ) ) {
 
 
184
  $wcap_check_cart_staus_need_to_update = self::wcal_update_abandoned_cart_status_for_placed_orders( $time_to_send_template_after, $cart_update_time, $value->user_id, $value->user_type, $value->id, $value->user_email );
185
  }
186
 
187
+ if ( false === $wcal_check_cart_needed_for_multiple_template && (int) $template_id === (int) $last_template_id ) {
188
+ $wpdb->update( // phpcs:ignore
189
+ $wpdb->prefix . 'ac_abandoned_cart_history_lite',
190
+ array(
191
+ 'email_reminder_status' => 'complete',
192
+ ),
193
+ array(
194
+ 'id' => $value->id,
195
+ )
196
+ );
197
+ }
198
+
199
+ if ( false === $wcal_check_cart_needed_for_multiple_template && false === $wcap_check_cart_staus_need_to_update ) {
200
 
201
  $cart_info_db = $value->abandoned_cart_info;
202
  $email_subject = $template_email_subject;
203
  $email_body = $email_body_template;
204
  $wcal_check_cart_total = $this->wcal_check_cart_total( $cart );
205
+ if ( true === $wcal_check_cart_total ) {
206
+ if ( 'GUEST' === $value->user_type ) {
207
  if ( isset( $results_guest[0]->billing_first_name ) ) {
208
  $email_body = str_ireplace( '{{customer.firstname}}', $results_guest[0]->billing_first_name, $email_body );
209
  $email_subject = str_ireplace( '{{customer.firstname}}', $results_guest[0]->billing_first_name, $email_subject );
221
  } else {
222
  $user_first_name = '';
223
  $user_first_name_temp = get_user_meta( $value->user_id, 'billing_first_name', true );
224
+ if ( isset( $user_first_name_temp ) && '' === $user_first_name_temp ) {
225
  $user_data = get_userdata( $user_id );
226
  if ( isset( $user_data->first_name ) ) {
227
  $user_first_name = $user_data->first_name;
235
  $email_subject = str_ireplace( '{{customer.firstname}}', $user_first_name, $email_subject );
236
  $user_last_name = '';
237
  $user_last_name_temp = get_user_meta( $value->user_id, 'billing_last_name', true );
238
+ if ( isset( $user_last_name_temp ) && '' === $user_last_name_temp ) {
239
  $user_data = get_userdata( $user_id );
240
  if ( isset( $user_data->last_name ) ) {
241
  $user_last_name = $user_data->last_name;
249
  $email_body = str_ireplace( '{{customer.fullname}}', $user_first_name . ' ' . $user_last_name, $email_body );
250
  }
251
  $order_date = '';
252
+ if ( $cart_update_time > 0 ) {
253
  $date_format = date_i18n( get_option( 'date_format' ), $cart_update_time );
254
  $time_format = date_i18n( get_option( 'time_format' ), $cart_update_time );
255
  $order_date = $date_format . ' ' . $time_format;
256
  }
257
  $email_body = str_ireplace( '{{cart.abandoned_date}}', $order_date, $email_body );
 
 
258
 
259
+ $wpdb->query( // phpcs:ignore
260
+ $wpdb->prepare(
261
+ "INSERT INTO `" . $wpdb->prefix . "ac_sent_history_lite` ( template_id, abandoned_order_id, sent_time, sent_email_id ) VALUES ( %s, %s, '" . current_time( 'mysql' ) . "', %s )", // phpcs:ignore
262
+ $template_id,
263
+ $value->id,
264
+ $value->user_email
265
+ )
266
+ );
267
+
268
+ $results_sent = $wpdb->get_results( // phpcs:ignore
269
+ $wpdb->prepare(
270
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_sent_history_lite` WHERE template_id = %s AND abandoned_order_id = %s ORDER BY id DESC LIMIT 1',
271
+ $template_id,
272
+ $value->id
273
+ )
274
+ );
275
  if ( count( $results_sent ) > 0 ) {
276
  $email_sent_id = $results_sent[0]->id;
277
  } else {
278
  $email_sent_id = '';
279
  }
280
 
281
+ if ( $email_sent_id > 0 ) {
282
 
283
  if ( $woocommerce->version < '2.3' ) {
284
  $cart_page_link = $woocommerce->cart->get_cart_url();
328
  </tr>';
329
  }
330
  $cart_details = $cart_info_db_field->cart;
331
+ $cart_total = 0;
332
+ $item_subtotal = 0;
333
+ $item_total = 0;
334
  $sub_line_prod_name = '';
335
  foreach ( $cart_details as $k => $v ) {
336
  $quantity_total = $v->quantity;
340
  $prod_name = get_post( $product_id );
341
  $product_link_track = get_permalink( $product_id );
342
  $product_name = $prod_name->post_title;
343
+ if ( '' === $sub_line_prod_name ) {
344
  $sub_line_prod_name = $product_name;
345
  }
346
+ // Item subtotal is calculated as product total including taxes.
347
+ if ( $v->line_tax > 0 ) {
348
  $item_subtotal = $item_subtotal + $v->line_total + $v->line_tax;
349
  } else {
350
  $item_subtotal = $item_subtotal + $v->line_total;
351
  }
352
+ // Line total.
353
  $item_total = $item_subtotal;
354
  $item_subtotal = $item_subtotal / $quantity_total;
355
  $item_total_display = wc_price( $item_total );
356
  $item_subtotal = wc_price( $item_subtotal );
357
+
358
  $prod_image = $product->get_image();
359
  $image_url = wp_get_attachment_url( get_post_thumbnail_id( $product_id ) );
360
  if ( strpos( $image_url, '/' ) === 0 ) {
361
  $image_url = get_option( 'siteurl' ) . $image_url;
362
  }
363
+ if ( isset( $v->variation_id ) && $v->variation_id > 0 ) {
364
  $variation_id = $v->variation_id;
365
  $variation = wc_get_product( $variation_id );
366
  $name = false !== $variation ? $variation->get_formatted_name() : '';
403
  <td> ' . apply_filters( 'wcal_reminder_email_line_subtotal_value', $item_total_display ) . '</td>
404
  </tr>';
405
  $cart_total += $item_total;
406
+ $item_subtotal = 0;
407
+ $item_total = 0;
408
  $p_exists = true;
409
  } else {
410
  $cart_total = 0;
411
+ $item_subtotal = 0;
412
+ $item_total = 0;
413
+ $p_exists = false;
414
  }
415
  }
416
 
437
  $user_email = $value->user_email;
438
  $email_body_final = stripslashes( $email_body );
439
  $email_body_final = convert_smilies( $email_body_final );
440
+ if ( isset( $is_wc_template ) && '1' === $is_wc_template ) {
441
  ob_start();
442
 
443
  wc_get_template( 'emails/email-header.php', array( 'email_heading' => $wc_template_header ) );
474
  * This function will check if the user type is Guest and the id is greater than 63000000
475
  * Then conider that as a correct guest user, if is not then do not send the emails
476
  *
477
+ * @param string|int $wcal_user_id User id.
478
+ * @param string $wcal_user_type User Type.
479
+ * @return boolean true | false.
480
  * @since 4.4
481
  */
482
  public static function wcal_get_is_guest_valid( $wcal_user_id, $wcal_user_type ) {
483
 
484
+ if ( 'REGISTERED' === $wcal_user_type ) {
485
  return true;
486
  }
487
 
488
+ if ( 'GUEST' === $wcal_user_type && $wcal_user_id >= 63000000 ) {
489
  return true;
490
  }
491
 
492
+ // It indicates that the user type is guest but the id for them is wrong.
 
 
493
  return false;
494
  }
495
 
496
  /**
497
  * It will check the cart total.
498
  *
499
+ * @param array|object $cart Cart details.
500
  * @return boolean true | false
501
  * @since 4.3
502
  */
503
+ public function wcal_check_cart_total( $cart ) {
504
  foreach ( $cart as $k => $v ) {
505
+ if ( $v->line_total > 0 ) {
506
  return true;
507
  }
508
  }
509
  return false;
510
  }
511
+
512
  /**
513
  * Get all carts which have the creation time earlier than the one that is passed.
514
  *
515
+ * @param string|timestamp $template_to_send_after_time Template time.
516
+ * @param string|timestamp $cart_abandon_cut_off_time Cutoff time.
517
+ * @param int $template_id - Email Template ID.
518
  * @globals mixed $wpdb
519
  * @return array | object $results
520
  * @since 1.3
521
  */
522
+ public function wcal_get_carts( $template_to_send_after_time, $cart_abandon_cut_off_time, $template_id ) {
523
  global $wpdb;
524
+ $cart_time = current_time( 'timestamp' ) - $template_to_send_after_time - $cart_abandon_cut_off_time; // phpcs:ignore
525
 
526
  $wcal_template_time = get_option( 'wcal_template_' . $template_id . '_time' );
527
  $wcal_add_template_condition = '';
530
  }
531
  $cart_ignored = 0;
532
  $unsubscribe = 0;
533
+
534
+ $results = $wpdb->get_results( // phpcs:ignore
535
+ $wpdb->prepare(
536
+ 'SELECT wpac . * , wpu.user_login, wpu.user_email
537
+ FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` AS wpac
538
+ LEFT JOIN ' . $wpdb->base_prefix . "users AS wpu ON wpac.user_id = wpu.id
539
+ WHERE cart_ignored = %s AND unsubscribe_link = %s AND abandoned_cart_time < %s
540
+ AND email_reminder_status <> 'complete'
541
+ $wcal_add_template_condition
542
+ ORDER BY `id` ASC ",
543
+ $cart_ignored,
544
+ $unsubscribe,
545
+ $cart_time
546
+ )
547
+ );
548
  return $results;
 
549
  }
550
 
551
  /**
552
  * It will update the abandoned cart staus if the order has been placed before sending the reminder emails.
553
  *
554
+ * @param string|timestamp $time_to_send_template_after Template time.
555
+ * @param string|timestamp $wcal_cart_time Abandoned time.
556
+ * @param string|int $wcal_user_id User id.
557
+ * @param string $wcal_user_type User type.
558
+ * @param string|int $wcal_cart_id Abandoned cart id.
559
+ * @param string $wcal_user_email User Email.
560
  * @globals mixed $wpdb
561
  * @return boolean true | false
562
  * @since 4.3
564
  public static function wcal_update_abandoned_cart_status_for_placed_orders( $time_to_send_template_after, $wcal_cart_time, $wcal_user_id, $wcal_user_type, $wcal_cart_id, $wcal_user_email ) {
565
  global $wpdb;
566
 
567
+ if ( $wcal_user_id >= '63000000' && 'GUEST' === $wcal_user_type ) {
568
  $updated_value = self::wcal_update_status_of_guest( $wcal_cart_id, $wcal_cart_time, $time_to_send_template_after, $wcal_user_email );
569
+ if ( 1 === $updated_value ) {
570
  return true;
571
  }
572
+ } elseif ( $wcal_user_id < '63000000' && 'REGISTERED' === $wcal_user_type ) {
573
  $updated_value = self::wcal_update_status_of_loggedin( $wcal_cart_id, $wcal_cart_time, $time_to_send_template_after, $wcal_user_email );
574
+ if ( 1 === $updated_value ) {
575
  return true;
576
  }
577
  }
581
  /**
582
  * It will update the Guest users abandoned cart staus if the order has been placed before sending the reminder emails.
583
  *
584
+ * @param string|int $cart_id Abandoned cart id.
585
+ * @param string|timestamp $abandoned_cart_time Abandoned time.
586
+ * @param string|timestamp $time_to_send_template_after Template time.
587
+ * @param string $wcal_user_email_address User Email.
588
  * @globals mixed $wpdb
589
+ * @return int 0|1
590
  * @since 4.3
591
  */
592
  public static function wcal_update_status_of_guest( $cart_id, $abandoned_cart_time, $time_to_send_template_after, $wcal_user_email_address ) {
593
  global $wpdb;
594
 
595
+ $results_query_email = $wpdb->get_results(
596
+ $wpdb->prepare(
597
+ "SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `" . $wpdb->prefix . "postmeta` AS wpm LEFT JOIN `" . $wpdb->prefix . "posts` AS wpost ON wpm.post_id = wpost.ID
598
+ WHERE wpm.meta_key = '_billing_email' AND wpm.meta_value = %s AND wpm.post_id = wpost.ID AND wpost.post_type = 'shop_order' Order BY wpm.post_id DESC LIMIT 1",
599
+ $wcal_user_email_address
600
+ )
601
+ );
602
 
603
+ // This will check that For abc@abc.com email address we have order for todays date in WC post table.
 
 
604
  if ( count( $results_query_email ) > 0 ) {
605
 
606
+ $current_time = current_time( 'timestamp' ); // phpcs:ignore
607
+ $todays_date = date( 'Y-m-d', $current_time ); // phpcs:ignore
608
 
609
  $order_date_with_time = $results_query_email[0]->post_date;
610
  $order_date = substr( $order_date_with_time, 0, 10 );
611
 
612
+ if ( $order_date == $todays_date ) { // phpcs:ignore
613
 
614
+ // In some cases the cart is recovered but it is not marked as the recovered. So here we check if any record is found for that cart id if yes then update the record respectively.
 
 
 
615
  $wcal_check_email_sent_to_cart = self::wcal_get_cart_sent_data( $cart_id );
616
 
617
+ if ( 0 !== $wcal_check_email_sent_to_cart ) {
618
 
619
+ $wcal_results = $wpdb->get_results( // phpcs:ignore
620
+ $wpdb->prepare(
621
+ 'SELECT `post_id` FROM `' . $wpdb->prefix . 'postmeta` WHERE meta_value = %s',
622
+ $cart_id
623
+ )
624
+ );
625
 
626
  if ( count( $wcal_results ) > 0 ) {
627
 
629
 
630
  $order = wc_get_order( $order_id );
631
 
632
+ $wpdb->query( // phpcs:ignore
633
+ $wpdb->prepare(
634
+ "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET recovered_cart= %s, cart_ignored = '1' WHERE id = %s", // phpcs:ignore
635
+ $order_id,
636
+ $cart_id
637
+ )
638
+ );
639
 
640
  $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-abandoned-cart' ) );
641
 
643
  delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', $wcal_check_email_sent_to_cart );
644
  }
645
  } else {
646
+ $wpdb->query( // phpcs:ignore
647
+ $wpdb->prepare(
648
+ "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id = %s", // phpcs:ignore
649
+ $cart_id
650
+ )
651
+ );
652
  }
653
  return 1;
654
  } elseif ( strtotime( $order_date_with_time ) > $abandoned_cart_time ) {
655
+ $wpdb->query( // phpcs:ignore
656
+ $wpdb->prepare(
657
+ "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id = %s ", // phpcs:ignore
658
+ $cart_id
659
+ )
660
+ );
661
  return 1;
662
+ } elseif ( 'wc-pending' === $results_query_email[0]->post_status || 'wc-failed' === $results_query_email[0]->post_status ) {
663
+ // If the post status are pending or failed the send them for abandoned cart reminder emails.
 
 
 
664
  return 0;
665
  }
666
  }
670
  /**
671
  * It will update the Loggedin users abandoned cart staus if the order has been placed before sending the reminder emails.
672
  *
673
+ * @param string|int $cart_id Abandoned cart id.
674
+ * @param string|timestamp $abandoned_cart_time Abandoned time.
675
+ * @param string|timestamp $time_to_send_template_after Template time.
676
+ * @param string $user_billing_email User Email.
677
  * @globals mixed $wpdb
678
+ * @return int 0|1
679
  * @since 4.3
680
  */
681
  public static function wcal_update_status_of_loggedin( $cart_id, $abandoned_cart_time, $time_to_send_template_after, $user_billing_email ) {
682
  global $wpdb;
683
 
684
+ $results_query_email = $wpdb->get_results( // phpcs:ignore
685
+ $wpdb->prepare(
686
+ "SELECT wpm.post_id, wpost.post_date, wpost.post_status FROM `" . $wpdb->prefix . "postmeta` AS wpm LEFT JOIN `" . $wpdb->prefix . "posts` AS wpost ON wpm.post_id = wpost.ID WHERE wpm.meta_key = '_billing_email' AND wpm.meta_value = %s AND wpm.post_id = wpost.ID Order BY wpm.post_id DESC LIMIT 1", // phpcs:ignore
687
+ $user_billing_email
688
+ )
689
+ );
690
 
691
  if ( count( $results_query_email ) > 0 ) {
692
+ $current_time = current_time( 'timestamp' ); // phpcs:ignore
693
+ $todays_date = date( 'Y-m-d', $current_time ); // phpcs:ignore
694
  $order_date_time = $results_query_email[0]->post_date;
695
  $order_date = substr( $order_date_time, 0, 10 );
696
 
697
+ if ( $order_date == $todays_date ) { // phpcs:ignore
698
 
699
  $wcal_check_email_sent_to_cart = self::wcal_get_cart_sent_data( $cart_id );
700
 
701
+ if ( $wcal_check_email_sent_to_cart > 0 ) {
702
 
703
+ $wcal_results = $wpdb->get_results( // phpcs:ignore
704
+ $wpdb->prepare(
705
+ 'SELECT `post_id` FROM `' . $wpdb->prefix . 'postmeta` WHERE meta_value = %s',
706
+ $cart_id
707
+ )
708
+ );
709
 
710
  if ( count( $wcal_results ) > 0 ) {
711
 
713
 
714
  $order = wc_get_order( $order_id );
715
 
716
+ $wpdb->query( // phpcs:ignore
717
+ "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET recovered_cart= '" . $order_id . "', cart_ignored = '1' WHERE id = '" . $cart_id . "'" // phpcs:ignore
718
+ );
719
 
720
  $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-abandoned-cart' ) );
721
 
723
  delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', $wcal_check_email_sent_to_cart );
724
  }
725
  } else {
726
+ $wpdb->query( // phpcs:ignore
727
+ "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'" // phpcs:ignore
728
+ );
729
  }
730
  return 1;
731
  } elseif ( strtotime( $order_date_time ) >= $abandoned_cart_time ) {
732
+ $wpdb->query( // phpcs:ignore
733
+ "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE id ='" . $cart_id . "'" // phpcs:ignore
734
+ );
735
  return 1; // We return here 1 so it indicate that the cart has been modifed so do not sent email and delete from the array.
736
+ } elseif ( 'wc-pending' === $results_query_email[0]->post_status || 'wc-failed' === $results_query_email[0]->post_status ) {
737
+ return 0; // if status of the order is pending or falied then return 0 so it will not delete that cart and send reminder email.
738
  }
739
  }
740
  return 0; // it means there are no record found to be update it.
743
  /**
744
  * It will check that for abandoned cart remider email has been sent.
745
  *
746
+ * @param string|int $wcal_cart_id Abandoned cart id.
747
+ * @return int|0 $wcal_sent_id Email sent id.
748
  * @globals mixed $wpdb
749
  * @since 4.3
750
  */
751
  public static function wcal_get_cart_sent_data( $wcal_cart_id ) {
752
  global $wpdb;
753
 
754
+ $wcal_results = $wpdb->get_results( // phpcs:ignore
755
+ $wpdb->prepare(
756
+ "SELECT id FROM `" . $wpdb->prefix . "ac_sent_history_lite` WHERE abandoned_order_id = %d ORDER BY 'id' DESC LIMIT 1 ", // phpcs:ignore
757
+ $wcal_cart_id
758
+ )
759
+ );
760
 
761
  if ( count( $wcal_results ) > 0 ) {
762
  $wcal_sent_id = $wcal_results[0]->id;
769
  * If none of the email has been sent for some time then from the time where it send the first email template it will consider
770
  * the time and further email will sent from first email sent time. So all template will not sent at the same time.
771
  *
772
+ * @param string|int $wcal_cart_id Abandoned cart id.
773
+ * @param string|timestamp $time_to_send_template_after Template time.
774
+ * @param string|int $template_id Template id.
775
  * @return boolean true | false
776
  * @globals mixed $wpdb
777
  * @since 3.1
779
  public static function wcal_remove_cart_for_mutiple_templates( $wcal_cart_id, $time_to_send_template_after, $template_id ) {
780
  global $wpdb;
781
 
782
+ $wcal_get_last_email_sent_time_results_list = $wpdb->get_results( // phpcs:ignore
783
+ "SELECT * FROM `" . $wpdb->prefix . "ac_sent_history_lite` WHERE abandoned_order_id = $wcal_cart_id ORDER BY `sent_time` DESC LIMIT 1" // phpcs:ignore
784
+ );
785
 
786
  if ( count( $wcal_get_last_email_sent_time_results_list ) > 0 ) {
787
  $last_template_send_time = strtotime( $wcal_get_last_email_sent_time_results_list[0]->sent_time );
788
  $second_template_send_time = $last_template_send_time + $time_to_send_template_after;
789
+ $current_time_test = current_time( 'timestamp' ); // phpcs:ignore
790
  if ( $second_template_send_time > $current_time_test ) {
791
  return true;
792
  }
797
  /**
798
  * This function is used to encode the validate string.
799
  *
800
+ * @param string $validate String to validate.
801
+ * @return encoded data $validate_encoded.
802
  * @since 1.3
803
  */
804
+ public function wcal_encrypt_validate( $validate ) {
805
+ $crypt_key = get_option( 'wcal_security_key' );
806
+ $validate_encoded = Wcal_Aes_Ctr::encrypt( $validate, $crypt_key, 256 );
807
  return( $validate_encoded );
808
  }
809
 
810
  /**
811
  * It will check if the reminder email has been sent to the abandoned cart.
812
  *
813
+ * @param string|int $user_id User id.
814
+ * @param string|timestamp $cart_update_time Abandoned cart time.
815
+ * @param string|int $template_id Template id.
816
+ * @param string|int $id Abandoned cart id.
817
  * @globals mixed $wpdb
818
+ * @return boolean true|false
819
  * @since 1.3
820
  */
821
+ public function wcal_check_sent_history( $user_id, $cart_update_time, $template_id, $id ) {
822
  global $wpdb;
 
 
 
823
 
824
+ $results = $wpdb->get_results( // phpcs:ignore
825
+ $wpdb->prepare(
826
+ "SELECT wpcs . * , wpac . abandoned_cart_time , wpac . user_id FROM `" . $wpdb->prefix . "ac_sent_history_lite` AS wpcs LEFT JOIN " . $wpdb->prefix . "ac_abandoned_cart_history_lite AS wpac ON wpcs.abandoned_order_id = wpac.id WHERE template_id = %s AND wpcs.abandoned_order_id = %d ORDER BY 'id' DESC LIMIT 1", // phpcs:ignore
827
+ $template_id,
828
+ $id
829
+ )
830
+ );
831
+ if ( count( $results ) === 0 ) {
832
  return true;
833
  } elseif ( $results[0]->abandoned_cart_time < $cart_update_time ) {
834
  return true;
includes/admin/class-wcal-personal-data-eraser.php ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Export Abandoned Carts data in
4
+ * Dashboard->Tools->Erase Personal Data
5
+ *
6
+ * @since 4.9
7
+ * @package Abandoned-Cart-Lite-for-WooCommerce\Data-Eraser
8
+ */
9
+
10
+ // Exit if accessed directly.
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+
15
+ if ( ! class_exists( 'Wcal_Personal_Data_Eraser' ) ) {
16
+
17
+ /**
18
+ * Export Abandoned Carts data in
19
+ * Dashboard->Tools->Erase Personal Data
20
+ */
21
+ class Wcal_Personal_Data_Eraser {
22
+
23
+ /**
24
+ * Construct.
25
+ *
26
+ * @since 4.9
27
+ */
28
+ public function __construct() {
29
+ // Hook into the WP erase process.
30
+ add_filter( 'wp_privacy_personal_data_erasers', array( &$this, 'wcal_eraser_array' ), 6 );
31
+ }
32
+
33
+ /**
34
+ * Add our eraser and it's callback function
35
+ *
36
+ * @param array $erasers - Any erasers that need to be added by 3rd party plugins.
37
+ * @return array $erasers - Erasers list containing our plugin details.
38
+ *
39
+ * @since 4.9
40
+ */
41
+ public static function wcal_eraser_array( $erasers = array() ) {
42
+
43
+ $eraser_list = array();
44
+ // Add our eraser and it's callback function.
45
+ $eraser_list['wcal_carts'] = array(
46
+ 'eraser_friendly_name' => __( 'Abandoned & Recovered Carts', 'woocommerce-abandoned-cart' ),
47
+ 'callback' => array( 'Wcal_Personal_Data_Eraser', 'wcal_data_eraser' ),
48
+ );
49
+
50
+ $erasers = array_merge( $erasers, $eraser_list );
51
+
52
+ return $erasers;
53
+
54
+ }
55
+
56
+ /**
57
+ * Erases personal data for abandoned carts.
58
+ *
59
+ * @param string $email_address - EMail Address for which personal data is being exported.
60
+ * @param integer $page - The Eraser page number.
61
+ * @return array $reponse - Whether the process was successful or no.
62
+ *
63
+ * @hook wp_privacy_personal_data_erasers
64
+ * @global $wpdb
65
+ * @since 4.9
66
+ */
67
+ public static function wcal_data_eraser( $email_address, $page ) {
68
+ global $wpdb;
69
+
70
+ $page = (int) $page;
71
+ $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
72
+ $erasure_enabled = wc_string_to_bool( get_option( 'woocommerce_erasure_request_removes_order_data', 'no' ) );
73
+ $response = array(
74
+ 'items_removed' => false,
75
+ 'items_retained' => false,
76
+ 'messages' => array(),
77
+ 'done' => true,
78
+ );
79
+
80
+ $user_id = $user ? (int) $user->ID : 0;
81
+
82
+ if ( $user_id > 0 ) { // registered user.
83
+ $cart_ids = $wpdb->get_results( // phpcs:ignore
84
+ $wpdb->prepare(
85
+ "SELECT id FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE user_id = %d AND user_type = 'REGISTERED'", // phpcs:ignore
86
+ $user_id
87
+ )
88
+ );
89
+ } else { // guest carts.
90
+ $guest_user_ids = $wpdb->get_results( // phpcs:ignore
91
+ $wpdb->prepare(
92
+ 'SELECT id FROM `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite` WHERE email_id = %s', // phpcs:ignore
93
+ $email_address
94
+ )
95
+ );
96
+
97
+ if ( 0 === count( $guest_user_ids ) ) {
98
+ return array(
99
+ 'messages' => array( __( 'No personal data found for any abandoned carts.', 'woocommerce-abandoned-cart' ) ),
100
+ 'items_removed' => false,
101
+ 'items_retained' => true,
102
+ 'done' => true,
103
+ );
104
+ }
105
+ $cart_ids = array();
106
+
107
+ foreach ( $guest_user_ids as $ids ) {
108
+ // Get the cart data.
109
+ $cart_data = $wpdb->get_results( // phpcs:ignore
110
+ $wpdb->prepare(
111
+ "SELECT id FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE user_id = %d AND user_type = 'GUEST'", // phpcs:ignore
112
+ $ids->id
113
+ )
114
+ );
115
+
116
+ $cart_ids = array_merge( $cart_ids, $cart_data );
117
+ }
118
+ }
119
+
120
+ if ( 0 < count( $cart_ids ) ) {
121
+
122
+ $cart_chunks = array_chunk( $cart_ids, 10, true );
123
+
124
+ $cart_export = isset( $cart_chunks[ $page - 1 ] ) ? $cart_chunks[ $page - 1 ] : array();
125
+ if ( count( $cart_export ) > 0 ) {
126
+ foreach ( $cart_export as $abandoned_ids ) {
127
+ $cart_id = $abandoned_ids->id;
128
+
129
+ if ( apply_filters( 'wcal_privacy_erase_cart_personal_data', $erasure_enabled, $cart_id ) ) {
130
+ self::remove_cart_personal_data( $cart_id );
131
+
132
+ // Translators: %s Abandoned Cart ID.
133
+ $response['messages'][] = sprintf( __( 'Removed personal data from cart %s.', 'woocommerce-abandoned-cart' ), $cart_id );
134
+ $response['items_removed'] = true;
135
+ } else {
136
+ // Translators: %s Abandoned Cart ID.
137
+ $response['messages'][] = sprintf( __( 'Personal data within cart %s has been retained.', 'woocommerce-abandoned-cart' ), $cart_id );
138
+ $response['items_retained'] = true;
139
+ }
140
+ }
141
+ $response['done'] = $page > count( $cart_chunks );
142
+ } else {
143
+ $response['done'] = true;
144
+ }
145
+ } else {
146
+ $response['done'] = true;
147
+ }
148
+ return $response;
149
+ }
150
+
151
+ /**
152
+ * Erases the personal data for each abandoned cart.
153
+ *
154
+ * @param integer $abandoned_id - Abandoned Cart ID.
155
+ * @global $wpdb
156
+ * @since 4.9
157
+ */
158
+ public static function remove_cart_personal_data( $abandoned_id ) {
159
+ global $wpdb;
160
+
161
+ $anonymized_cart = array();
162
+ $anonymized_guest = array();
163
+
164
+ do_action( 'wcal_privacy_before_remove_cart_personal_data', $abandoned_id );
165
+
166
+ // list the props we'll be anonymizing for cart history table.
167
+ $props_to_remove_cart = apply_filters(
168
+ 'wcal_privacy_remove_cart_personal_data_props',
169
+ array(
170
+ 'session_id' => 'numeric_id',
171
+ ),
172
+ $abandoned_id
173
+ );
174
+
175
+ // list the props we'll be anonymizing for guest cart history table.
176
+ $props_to_remove_guest = apply_filters(
177
+ 'wcal_privacy_remove_cart_personal_data_props_guest',
178
+ array(
179
+ 'billing_first_name' => 'text',
180
+ 'billing_last_name' => 'text',
181
+ 'phone' => 'phone',
182
+ 'email_id' => 'email',
183
+ ),
184
+ $abandoned_id
185
+ );
186
+
187
+ if ( ! empty( $props_to_remove_cart ) && is_array( $props_to_remove_cart ) ) {
188
+
189
+ // get the data from cart history.
190
+ $cart_details = $wpdb->get_results( // phpcs:ignore
191
+ $wpdb->prepare(
192
+ 'SELECT session_id, user_type, user_id FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE id = %d',
193
+ $abandoned_id
194
+ )
195
+ );
196
+
197
+ if ( count( $cart_details ) > 0 ) {
198
+ $cart_details = $cart_details[0];
199
+ } else {
200
+ return;
201
+ }
202
+
203
+ $user_id = $cart_details->user_id;
204
+ $user_type = $cart_details->user_type;
205
+
206
+ foreach ( $props_to_remove_cart as $prop => $data_type ) {
207
+
208
+ $value = $cart_details->$prop;
209
+
210
+ if ( empty( $value ) || empty( $data_type ) ) {
211
+ continue;
212
+ }
213
+
214
+ if ( function_exists( 'wp_privacy_anonymize_data' ) ) {
215
+ $anon_value = wp_privacy_anonymize_data( $data_type, $value );
216
+ } else {
217
+ $anon_value = '';
218
+ }
219
+
220
+ $anonymized_cart[ $prop ] = apply_filters( 'wcal_privacy_remove_cart_personal_data_prop_value', $anon_value, $prop, $value, $data_type, $abandoned_id );
221
+ }
222
+ $anonymized_cart['user_type'] = __( 'ANONYMIZED', 'woocommerce-abandoned-cart' );
223
+ // update the DB.
224
+ $wpdb->update( // phpcs:ignore
225
+ $wpdb->prefix . 'ac_abandoned_cart_history_lite',
226
+ $anonymized_cart,
227
+ array( 'id' => $abandoned_id )
228
+ );
229
+ }
230
+
231
+ // check whether it's a guest user.
232
+ if ( 'GUEST' === $user_type && ! empty( $props_to_remove_guest ) && is_array( $props_to_remove_guest ) ) {
233
+
234
+ // get the data from guest cart history.
235
+ $guest_details = $wpdb->get_results( // phpcs:ignore
236
+ $wpdb->prepare(
237
+ 'SELECT billing_first_name, billing_last_name, phone, email_id FROM `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite` WHERE id = %d',
238
+ $user_id
239
+ )
240
+ );
241
+
242
+ if ( count( $guest_details ) > 0 ) {
243
+ $guest_details = $guest_details[0];
244
+ } else {
245
+ return;
246
+ }
247
+
248
+ foreach ( $props_to_remove_guest as $prop => $data_type ) {
249
+ $value = $guest_details->$prop;
250
+
251
+ if ( empty( $value ) || empty( $data_type ) ) {
252
+ continue;
253
+ }
254
+
255
+ if ( function_exists( 'wp_privacy_anonymize_data' ) ) {
256
+ $anon_value = wp_privacy_anonymize_data( $data_type, $value );
257
+ } else {
258
+ $anon_value = '';
259
+ }
260
+
261
+ $anonymized_guest[ $prop ] = apply_filters( 'wcal_privacy_remove_cart_personal_data_prop_value_guest', $anon_value, $prop, $value, $data_type, $abandoned_id );
262
+ }
263
+ // update the DB.
264
+ $wpdb->update( // phpcs:ignore
265
+ $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite',
266
+ $anonymized_guest,
267
+ array( 'id' => $user_id )
268
+ );
269
+
270
+ }
271
+
272
+ }
273
+
274
+ } // end of class
275
+ $wcal_personal_data_eraser = new Wcal_Personal_Data_Eraser();
276
+ } // end if
277
+
includes/admin/class-wcal-privacy-export.php ADDED
@@ -0,0 +1,389 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Export Abandoned Carts data in
4
+ * Dashboard->Tools->Export Personal Data
5
+ *
6
+ * @since 4.9
7
+ */
8
+ // Exit if accessed directly
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ if ( ! class_exists( 'Wcal_Personal_Data_Export' ) ) {
14
+
15
+ /**
16
+ * Export Abandoned Carts data in
17
+ * Dashboard->Tools->Export Personal Data
18
+ */
19
+ class Wcal_Personal_Data_Export {
20
+
21
+ /**
22
+ * Construct
23
+ *
24
+ * @since 7.8
25
+ */
26
+ public function __construct() {
27
+ // Hook into the WP export process
28
+ add_filter( 'wp_privacy_personal_data_exporters', array( &$this, 'wcal_exporter_array' ), 6 );
29
+ }
30
+
31
+ /**
32
+ * Add our export and it's callback function
33
+ *
34
+ * @param array $exporters - Any exportes that need to be added by 3rd party plugins
35
+ * @param array $exporters - Exportes list containing our plugin details
36
+ *
37
+ * @since 4.9
38
+ */
39
+ public static function wcal_exporter_array( $exporters = array() ) {
40
+
41
+ $exporter_list = array();
42
+ // Add our export and it's callback function
43
+ $exporter_list['wcal_carts'] = array(
44
+ 'exporter_friendly_name' => __( 'Abandoned & Recovered Carts', 'woocommerce-abandoned-cart' ),
45
+ 'callback' => array( 'Wcal_Personal_Data_Export', 'wcal_data_exporter' ),
46
+ );
47
+
48
+ $exporters = array_merge( $exporters, $exporter_list );
49
+
50
+ return $exporters;
51
+
52
+ }
53
+
54
+ /**
55
+ * Returns data to be displayed for exporting the
56
+ * cart details
57
+ *
58
+ * @param string $email_address - EMail Address for which personal data is being exported
59
+ * @param integer $page - The Export page number
60
+ * @return array $data_to_export - Data to be exported
61
+ *
62
+ * @hook wp_privacy_personal_data_exporters
63
+ * @global $wpdb
64
+ * @since 4.9
65
+ */
66
+ static function wcal_data_exporter( $email_address, $page ) {
67
+
68
+ global $wpdb;
69
+
70
+ $done = false;
71
+ $page = (int) $page;
72
+ $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
73
+ $data_to_export = array();
74
+ $blank_cart_info = '{"cart":[]}';
75
+ $blank_cart_info_guest = '[]';
76
+ $blank_cart = '""';
77
+
78
+ $user_id = $user ? (int) $user->ID : 0;
79
+
80
+ if ( $user_id > 0 ) { // registered user
81
+
82
+ $cart_query = 'SELECT id FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . "`
83
+ WHERE user_id = %d AND
84
+ user_type = 'REGISTERED' AND abandoned_cart_info NOT LIKE '%$blank_cart_info%' AND abandoned_cart_info NOT LIKE '$blank_cart'";
85
+
86
+ $cart_ids = $wpdb->get_results( $wpdb->prepare( $cart_query, $user_id ) );
87
+ } else { // guest carts
88
+ $guest_query = 'SELECT id FROM `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite' . '`
89
+ WHERE email_id = %s';
90
+
91
+ $guest_user_ids = $wpdb->get_results( $wpdb->prepare( $guest_query, $email_address ) );
92
+
93
+ if ( 0 == count( $guest_user_ids ) ) {
94
+ return array(
95
+ 'data' => array(),
96
+ 'done' => true,
97
+ );
98
+ }
99
+
100
+ $cart_ids = array();
101
+
102
+ foreach ( $guest_user_ids as $ids ) {
103
+ // get the cart data
104
+ $cart_query = 'SELECT id, abandoned_cart_info AS cart_info FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . "`
105
+ WHERE user_id = %d AND
106
+ user_type = 'GUEST'";
107
+
108
+ $cart_data = $wpdb->get_results( $wpdb->prepare( $cart_query, $ids->id ) );
109
+
110
+ $cart_ids = array_merge( $cart_ids, $cart_data );
111
+ }
112
+ }
113
+
114
+ if ( 0 < count( $cart_ids ) ) {
115
+
116
+ $cart_chunks = array_chunk( $cart_ids, 10, true );
117
+
118
+ $cart_export = isset( $cart_chunks[ $page - 1 ] ) ? $cart_chunks[ $page - 1 ] : array();
119
+ if ( count( $cart_export ) > 0 ) {
120
+
121
+ foreach ( $cart_export as $abandoned_ids ) {
122
+
123
+ $cart_id = $abandoned_ids->id;
124
+ if ( count( $abandoned_ids->id ) > 0 ) {
125
+ $data_to_export[] = array(
126
+ 'group_id' => 'wcal_carts',
127
+ 'group_label' => __( 'Abandoned Carts', 'woocommerce-abandoned-cart' ),
128
+ 'item_id' => 'cart-' . $cart_id,
129
+ 'data' => self::get_cart_data( $cart_id ),
130
+ );
131
+ }
132
+ }
133
+ $done = $page > count( $cart_chunks );
134
+ } else {
135
+ $done = true;
136
+ }
137
+ } else {
138
+ $done = true;
139
+ }
140
+
141
+ return array(
142
+ 'data' => $data_to_export,
143
+ 'done' => $done,
144
+ );
145
+
146
+ }
147
+
148
+ /**
149
+ * Returns the personal data for each abandoned cart
150
+ *
151
+ * @param integer $abandoned_id - Abandoned Cart ID
152
+ * @return array $personal_data - Personal data to be displayed
153
+ * @global $wpdb
154
+ * @since 4.9
155
+ */
156
+ static function get_cart_data( $abandoned_id ) {
157
+ $personal_data = array();
158
+
159
+ global $wpdb;
160
+
161
+ $cart_query = 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . '`
162
+ WHERE id = %d';
163
+ $cart_details = $wpdb->get_results( $wpdb->prepare( $cart_query, $abandoned_id ) );
164
+ $cart_details = $cart_details[0];
165
+ $user_id = $cart_details->user_id;
166
+ $user_type = $cart_details->user_type;
167
+
168
+ if ( $user_type == 'GUEST' ) {
169
+
170
+ $cart_details_to_export = apply_filters(
171
+ 'wcal_personal_export_cart_details_prop',
172
+ array(
173
+ 'cart_id' => __( 'Abandoned Cart ID', 'woocommerce-abandoned-cart' ),
174
+ 'date_created' => __( 'Abandoned Date', 'woocommerce-abandoned-cart' ),
175
+ 'cart_status' => __( 'Abandoned Cart Status', 'woocommerce-abandoned-cart' ),
176
+ 'total' => __( 'Cart Total', 'woocommerce-abandoned-cart' ),
177
+ 'items' => __( 'Items Present', 'woocommerce-abandoned-cart' ),
178
+ 'session_id' => __( 'Session ID', 'woocommerce-abandoned-cart' ),
179
+ 'formatted_billing_address' => __( 'Billing Address', 'woocommerce-abandoned-cart' ),
180
+ 'billing_email' => __( 'Email Address', 'woocommerce-abandoned-cart' ),
181
+ ),
182
+ $abandoned_id
183
+ );
184
+
185
+ } else {
186
+ $cart_details_to_export = apply_filters(
187
+ 'wcal_personal_export_cart_details_prop',
188
+ array(
189
+ 'cart_id' => __( 'Abandoned Cart ID', 'woocommerce-abandoned-cart' ),
190
+ 'date_created' => __( 'Abandoned Date', 'woocommerce-abandoned-cart' ),
191
+ 'cart_status' => __( 'Abandoned Cart Status', 'woocommerce-abandoned-cart' ),
192
+ 'total' => __( 'Cart Total', 'woocommerce-abandoned-cart' ),
193
+ 'items' => __( 'Items Present', 'woocommerce-abandoned-cart' ),
194
+ 'formatted_billing_address' => __( 'Billing Address', 'woocommerce-abandoned-cart' ),
195
+ 'billing_email' => __( 'Email Address', 'woocommerce-abandoned-cart' ),
196
+ ),
197
+ $abandoned_id
198
+ );
199
+
200
+ }
201
+
202
+ $cart_data = json_decode( stripslashes( $cart_details->abandoned_cart_info ) );
203
+ $cart_info = $cart_data->cart;
204
+
205
+ if ( count( $cart_info ) > 0 ) {
206
+ $cart_details_formatted = self::wcal_get_cart_details_export( $cart_info );
207
+ }
208
+
209
+ if ( 'GUEST' == $user_type ) {
210
+ $guest_details = self::wcal_get_guest_personal_info( $user_id );
211
+ }
212
+ foreach ( $cart_details_to_export as $prop => $name ) {
213
+
214
+ switch ( $prop ) {
215
+ case 'cart_id':
216
+ $value = $cart_details->id;
217
+ break;
218
+ case 'date_created':
219
+ $value = date( 'Y-m-d H:i:s', $cart_details->abandoned_cart_time );
220
+ break;
221
+ case 'cart_status':
222
+ $cart_ignored = $cart_details->cart_ignored;
223
+
224
+ switch ( $cart_ignored ) {
225
+ case '0':
226
+ $value = $cart_details->recovered_cart > 0 ? __( 'Cart Recovered - Order #', 'woocommerce-abandoned-cart' ) . $cart_details->recovered_cart : __( 'Abandoned', 'woocommerce-abandoned-cart' );
227
+ break;
228
+ case '1':
229
+ $value = $cart_details->recovered_cart > 0 ? __( 'Cart Recovered - Order #', 'woocommerce-abandoned-cart' ) . $cart_details->recovered_cart : __( 'Abandoned but new cart created', 'woocommerce-abandoned-cart' );
230
+ break;
231
+ case '2':
232
+ $value = __( 'Abandoned - Unpaid Order #', 'woocommerce-abandoned-cart' ) . $cart_details->recovered_cart;
233
+ break;
234
+ }
235
+ break;
236
+ case 'total':
237
+ $total = 0;
238
+
239
+ if ( count( $cart_info ) > 0 ) {
240
+ foreach ( $cart_info as $k => $v ) {
241
+
242
+ $total += $cart_details_formatted[ $k ]['item_total'];
243
+ }
244
+ }
245
+ $value = wc_price( $total );
246
+ break;
247
+ case 'items':
248
+ $value = '';
249
+
250
+ if ( count( $cart_info ) > 0 ) {
251
+ foreach ( $cart_info as $k => $v ) {
252
+
253
+ $product_name = $cart_details_formatted[ $k ]['product_name'];
254
+ $qty = $cart_details_formatted[ $k ]['qty'];
255
+
256
+ $value .= ( $value == '' ) ? "$product_name x $qty" : ", $product_name x $qty";
257
+ }
258
+ }
259
+ break;
260
+ case 'formatted_billing_address':
261
+ if ( $user_type == 'REGISTERED' ) { // registered user
262
+
263
+ $billing = wcal_common::wcal_get_billing_details( $user_id );
264
+ $value = get_user_meta( $user_id, 'billing_first_name', true ); // First Name
265
+ $value .= ' ' . get_user_meta( $user_id, 'billing_last_name', true ); // Last Name
266
+ if ( count( $billing ) > 0 ) {
267
+ foreach ( $billing as $details ) {
268
+ if ( '' != $details ) {
269
+ $value .= ",$details ";
270
+ }
271
+ }
272
+ }
273
+ } elseif ( 'GUEST' == $user_type ) {
274
+ if ( count( $guest_details ) > 0 ) {
275
+ $value = $guest_details->billing_first_name; // First Name
276
+ $value .= ' ' . $guest_details->billing_last_name; // Last Name
277
+ }
278
+ }
279
+ break;
280
+
281
+ case 'billing_email':
282
+ if ( 'REGISTERED' == $user_type ) { // registered user
283
+ $value = get_user_meta( $user_id, $prop, true );
284
+ } elseif ( 'GUEST' == $user_type ) {
285
+ if ( count( $guest_details ) > 0 ) {
286
+ $value = $guest_details->$prop;
287
+ }
288
+ }
289
+ break;
290
+ default:
291
+ $value = ( isset( $cart_details->$prop ) ) ? $cart_details->$prop : '';
292
+ break;
293
+ }
294
+
295
+ $value = apply_filters( 'wcal_personal_export_cart_details_prop_value', $value, $prop, $cart_details );
296
+
297
+ $personal_data[] = array(
298
+ 'name' => $name,
299
+ 'value' => $value,
300
+ );
301
+
302
+ }
303
+ $personal_data = apply_filters( 'wcal_personal_data_cart_details_export', $personal_data, $cart_details );
304
+
305
+ return $personal_data;
306
+ }
307
+
308
+ /**
309
+ * Returns the personal data from the plugin guest cart table
310
+ * for guest abandoned carts
311
+ *
312
+ * @param integer $user_id - User ID
313
+ * @return array $guest_details - Guest personal details
314
+ * @global $wpdb
315
+ * @since 4.9
316
+ */
317
+ static function wcal_get_guest_personal_info( $user_id ) {
318
+ global $wpdb;
319
+ $guest_details = array();
320
+
321
+ $guest_query = 'SELECT billing_first_name, billing_last_name, email_id AS billing_email, phone AS billing_phone FROM `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite' . '`
322
+ WHERE id = %d';
323
+
324
+ $guest_details = $wpdb->get_results( $wpdb->prepare( $guest_query, $user_id ) );
325
+
326
+ if ( is_array( $guest_details ) && count( $guest_details ) > 0 ) {
327
+ $guest_details = $guest_details[0];
328
+ }
329
+
330
+ return $guest_details;
331
+ }
332
+
333
+ /**
334
+ * Returns the Cart Details such as quantity, product name
335
+ * etc.
336
+ *
337
+ * @param object $cart_info - Abandoned Cart Information
338
+ * @return array $cart_details - Array containing product, qty & total for each item
339
+ * @since 4.9
340
+ */
341
+ static function wcal_get_cart_details_export( $cart_info ) {
342
+
343
+ $cart_details = array();
344
+
345
+ if ( count( $cart_info ) > 0 ) {
346
+
347
+ $cart_total = 0;
348
+ foreach ( $cart_info as $k => $item_detail ) {
349
+
350
+ // Qty
351
+ $qty = $item_detail->quantity;
352
+
353
+ // Product Name
354
+ $product_id = $item_detail->product_id;
355
+ $prod_obj = wc_get_product( $product_id );
356
+ $product_name = $prod_obj->get_name();
357
+
358
+ // Variation Name
359
+ if ( isset( $item_detail->variation_id ) && $item_detail->variation_id > 0 ) {
360
+ $variation_id = $item_detail->variation_id;
361
+ $variation = wc_get_product( $variation_id );
362
+ $variation_name = $variation->get_name();
363
+
364
+ $product_name = $variation_name;
365
+ }
366
+
367
+ // Total
368
+ $item_total = $item_detail->line_total;
369
+ if ( $item_detail->line_subtotal_tax > 0 ) {
370
+ $item_total += $item_detail->line_subtotal_tax;
371
+ }
372
+
373
+ // Populate the array
374
+ $cart_details[ $k ]['qty'] = $qty;
375
+ $cart_details[ $k ]['product_name'] = $product_name;
376
+ $cart_details[ $k ]['item_total'] = $item_total;
377
+
378
+ $cart_total += $item_total;
379
+ }
380
+
381
+ $cart_details['total'] = $cart_total;
382
+ }
383
+
384
+ return $cart_details;
385
+ }
386
+ } // end of class
387
+ $Wcal_Personal_Data_Export = new Wcal_Personal_Data_Export();
388
+ } // end if
389
+
includes/admin/wcal_privacy_erase.php DELETED
@@ -1,248 +0,0 @@
1
- <?php
2
- /**
3
- * Export Abandoned Carts data in
4
- * Dashboard->Tools->Erase Personal Data
5
- *
6
- * @since 4.9
7
- */
8
- // Exit if accessed directly
9
- if ( ! defined( 'ABSPATH' ) ) exit;
10
-
11
- if ( ! class_exists('Wcal_Personal_Data_Eraser' ) ) {
12
-
13
- /**
14
- * Export Abandoned Carts data in
15
- * Dashboard->Tools->Erase Personal Data
16
- */
17
- class Wcal_Personal_Data_Eraser {
18
-
19
- /**
20
- * Construct
21
- * @since 4.9
22
- */
23
- public function __construct() {
24
- // Hook into the WP erase process
25
- add_filter( 'wp_privacy_personal_data_erasers', array( &$this, 'wcal_eraser_array' ), 6 );
26
- }
27
-
28
- /**
29
- * Add our eraser and it's callback function
30
- *
31
- * @param array $erasers - Any erasers that need to be added by 3rd party plugins
32
- * @param array $erasers - Erasers list containing our plugin details
33
- *
34
- * @since 4.9
35
- */
36
- public static function wcal_eraser_array( $erasers = array() ) {
37
-
38
- $eraser_list = array();
39
- // Add our eraser and it's callback function
40
- $eraser_list[ 'wcal_carts' ] = array(
41
- 'eraser_friendly_name' => __( 'Abandoned & Recovered Carts', 'woocommerce-abandoned-cart' ),
42
- 'callback' => array( 'Wcal_Personal_Data_Eraser', 'wcal_data_eraser' )
43
- );
44
-
45
- $erasers = array_merge( $erasers, $eraser_list );
46
-
47
- return $erasers;
48
-
49
- }
50
-
51
- /**
52
- * Erases personal data for abandoned carts.
53
- *
54
- * @param string $email_address - EMail Address for which personal data is being exported
55
- * @param integer $page - The Eraser page number
56
- * @return array $reponse - Whether the process was successful or no
57
- *
58
- * @hook wp_privacy_personal_data_erasers
59
- * @global $wpdb
60
- * @since 4.9
61
- */
62
- static function wcal_data_eraser( $email_address, $page ) {
63
- global $wpdb;
64
-
65
- $page = (int) $page;
66
- $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
67
- $erasure_enabled = wc_string_to_bool( get_option( 'woocommerce_erasure_request_removes_order_data', 'no' ) );
68
- $response = array(
69
- 'items_removed' => false,
70
- 'items_retained' => false,
71
- 'messages' => array(),
72
- 'done' => true,
73
- );
74
-
75
- $user_id = $user ? (int) $user->ID : 0;
76
-
77
- if( $user_id > 0 ) { // registered user
78
- $cart_query = "SELECT id FROM `" . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . "`
79
- WHERE user_id = %d AND
80
- user_type = 'REGISTERED'";
81
-
82
- $cart_ids = $wpdb->get_results( $wpdb->prepare( $cart_query, $user_id ) );
83
- } else { // guest carts
84
- $guest_query = "SELECT id FROM `" . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite' . "`
85
- WHERE email_id = %s";
86
-
87
- $guest_user_ids = $wpdb->get_results( $wpdb->prepare( $guest_query, $email_address ) );
88
-
89
- if ( 0 == count( $guest_user_ids ) ) {
90
- return array( 'messages' => array( __( 'No personal data found for any abandoned carts.', 'woocommerce-abandoned-cart' ) ),
91
- 'items_removed' => false,
92
- 'items_retained' => true,
93
- 'done' => true
94
- );
95
- }
96
- $cart_ids = array();
97
-
98
- foreach( $guest_user_ids as $ids ) {
99
- // get the cart data
100
- $cart_query = "SELECT id FROM `" . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . "`
101
- WHERE user_id = %d AND
102
- user_type = 'GUEST'";
103
-
104
- $cart_data = $wpdb->get_results( $wpdb->prepare( $cart_query, $ids->id ) );
105
-
106
- $cart_ids = array_merge( $cart_ids, $cart_data );
107
- }
108
- }
109
-
110
- if ( 0 < count( $cart_ids ) ) {
111
-
112
- $cart_chunks = array_chunk( $cart_ids, 10, true );
113
-
114
- $cart_export = isset( $cart_chunks[ $page - 1 ] ) ? $cart_chunks[ $page - 1 ] : array();
115
- if( count( $cart_export ) > 0 ) {
116
- foreach ( $cart_export as $abandoned_ids ) {
117
- $cart_id = $abandoned_ids->id;
118
-
119
- if ( apply_filters( 'wcal_privacy_erase_cart_personal_data', $erasure_enabled, $cart_id ) ) {
120
- self::remove_cart_personal_data( $cart_id );
121
-
122
- /* Translators: %s Abandoned Cart ID. */
123
- $response['messages'][] = sprintf( __( 'Removed personal data from cart %s.', 'woocommerce-abandoned-cart' ), $cart_id );
124
- $response['items_removed'] = true;
125
- } else {
126
- /* Translators: %s Abandoned Cart ID. */
127
- $response['messages'][] = sprintf( __( 'Personal data within cart %s has been retained.', 'woocommerce-abandoned-cart' ), $cart_id );
128
- $response['items_retained'] = true;
129
- }
130
-
131
- }
132
- $response['done'] = $page > count( $cart_chunks );
133
- } else {
134
- $response['done'] = true;
135
- }
136
- } else {
137
- $response['done'] = true;
138
- }
139
- return $response;
140
- }
141
-
142
- /**
143
- * Erases the personal data for each abandoned cart
144
- *
145
- * @param integer $abandoned_id - Abandoned Cart ID
146
- * @global $wpdb
147
- * @since 4.9
148
- */
149
- static function remove_cart_personal_data( $abandoned_id ) {
150
- global $wpdb;
151
-
152
- $anonymized_cart = array();
153
- $anonymized_guest = array();
154
-
155
- do_action( 'wcal_privacy_before_remove_cart_personal_data', $abandoned_id );
156
-
157
- // list the props we'll be anonymizing for cart history table
158
- $props_to_remove_cart = apply_filters( 'wcal_privacy_remove_cart_personal_data_props', array(
159
- 'session_id' => 'numeric_id',
160
- ),
161
- $abandoned_id
162
- );
163
-
164
- // list the props we'll be anonymizing for guest cart history table
165
- $props_to_remove_guest = apply_filters( 'wcal_privacy_remove_cart_personal_data_props_guest', array(
166
- 'billing_first_name' => 'text',
167
- 'billing_last_name' => 'text',
168
- 'phone' => 'phone',
169
- 'email_id' => 'email' ), $abandoned_id );
170
-
171
-
172
- if ( ! empty( $props_to_remove_cart ) && is_array( $props_to_remove_cart ) ) {
173
-
174
- // get the data from cart history
175
- $cart_query = "SELECT session_id, user_type, user_id FROM `" . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . "`
176
- WHERE id = %d";
177
- $cart_details = $wpdb->get_results( $wpdb->prepare( $cart_query, $abandoned_id ) );
178
-
179
- if( count( $cart_details ) > 0 ) {
180
- $cart_details = $cart_details[0];
181
- } else {
182
- return;
183
- }
184
-
185
- $user_id = $cart_details->user_id;
186
- $user_type = $cart_details->user_type;
187
-
188
- foreach ( $props_to_remove_cart as $prop => $data_type ) {
189
-
190
- $value = $cart_details->$prop;
191
-
192
- if ( empty( $value ) || empty( $data_type ) ) {
193
- continue;
194
- }
195
-
196
- if ( function_exists( 'wp_privacy_anonymize_data' ) ) {
197
- $anon_value = wp_privacy_anonymize_data( $data_type, $value );
198
- } else {
199
- $anon_value = '';
200
- }
201
-
202
- $anonymized_cart[ $prop ] = apply_filters( 'wcal_privacy_remove_cart_personal_data_prop_value', $anon_value, $prop, $value, $data_type, $abandoned_id );
203
- }
204
- $anonymized_cart[ 'user_type' ] = __( 'ANONYMIZED', 'woocommerce-abandoned-cart' );
205
- // update the DB
206
- $wpdb->update( $wpdb->prefix . 'ac_abandoned_cart_history_lite', $anonymized_cart, array( 'id' => $abandoned_id ) );
207
- }
208
-
209
- // check whether it's a guest user
210
- if( 'GUEST' == $user_type && ! empty( $props_to_remove_guest ) && is_array( $props_to_remove_guest ) ) {
211
-
212
- // get the data from guest cart history
213
- $guest_query = "SELECT billing_first_name, billing_last_name, phone, email_id FROM `" . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite' . "`
214
- WHERE id = %d";
215
- $guest_details = $wpdb->get_results( $wpdb->prepare( $guest_query, $user_id ) );
216
-
217
- if ( count( $guest_details ) > 0 ) {
218
- $guest_details = $guest_details[0];
219
- } else {
220
- return;
221
- }
222
-
223
- foreach ( $props_to_remove_guest as $prop => $data_type ) {
224
- $value = $guest_details->$prop;
225
-
226
- if ( empty( $value ) || empty( $data_type ) ) {
227
- continue;
228
- }
229
-
230
- if ( function_exists( 'wp_privacy_anonymize_data' ) ) {
231
- $anon_value = wp_privacy_anonymize_data( $data_type, $value );
232
- } else {
233
- $anon_value = '';
234
- }
235
-
236
- $anonymized_guest[ $prop ] = apply_filters( 'wcal_privacy_remove_cart_personal_data_prop_value_guest', $anon_value, $prop, $value, $data_type, $abandoned_id );
237
- }
238
- // update the DB
239
- $wpdb->update( $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite', $anonymized_guest, array( 'id' => $user_id ) );
240
-
241
- }
242
-
243
- }
244
-
245
- } // end of class
246
- $Wcal_Personal_Data_Eraser = new Wcal_Personal_Data_Eraser();
247
- } // end if
248
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/wcal_privacy_export.php DELETED
@@ -1,380 +0,0 @@
1
- <?php
2
- /**
3
- * Export Abandoned Carts data in
4
- * Dashboard->Tools->Export Personal Data
5
- *
6
- * @since 4.9
7
- */
8
- // Exit if accessed directly
9
- if ( ! defined( 'ABSPATH' ) ) exit;
10
-
11
- if ( ! class_exists('Wcal_Personal_Data_Export' ) ) {
12
-
13
- /**
14
- * Export Abandoned Carts data in
15
- * Dashboard->Tools->Export Personal Data
16
- */
17
- class Wcal_Personal_Data_Export {
18
-
19
- /**
20
- * Construct
21
- * @since 7.8
22
- */
23
- public function __construct() {
24
- // Hook into the WP export process
25
- add_filter( 'wp_privacy_personal_data_exporters', array( &$this, 'wcal_exporter_array' ), 6 );
26
- }
27
-
28
- /**
29
- * Add our export and it's callback function
30
- *
31
- * @param array $exporters - Any exportes that need to be added by 3rd party plugins
32
- * @param array $exporters - Exportes list containing our plugin details
33
- *
34
- * @since 4.9
35
- */
36
- public static function wcal_exporter_array( $exporters = array() ) {
37
-
38
- $exporter_list = array();
39
- // Add our export and it's callback function
40
- $exporter_list[ 'wcal_carts' ] = array(
41
- 'exporter_friendly_name' => __( 'Abandoned & Recovered Carts', 'woocommerce-abandoned-cart' ),
42
- 'callback' => array( 'Wcal_Personal_Data_Export', 'wcal_data_exporter' )
43
- );
44
-
45
- $exporters = array_merge( $exporters, $exporter_list );
46
-
47
- return $exporters;
48
-
49
- }
50
-
51
- /**
52
- * Returns data to be displayed for exporting the
53
- * cart details
54
- *
55
- * @param string $email_address - EMail Address for which personal data is being exported
56
- * @param integer $page - The Export page number
57
- * @return array $data_to_export - Data to be exported
58
- *
59
- * @hook wp_privacy_personal_data_exporters
60
- * @global $wpdb
61
- * @since 4.9
62
- */
63
- static function wcal_data_exporter( $email_address, $page ) {
64
-
65
- global $wpdb;
66
-
67
- $done = false;
68
- $page = (int) $page;
69
- $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
70
- $data_to_export = array();
71
- $blank_cart_info = '{"cart":[]}';
72
- $blank_cart_info_guest = '[]';
73
- $blank_cart = '""';
74
-
75
- $user_id = $user ? (int) $user->ID : 0;
76
-
77
- if ( $user_id > 0 ) { // registered user
78
-
79
- $cart_query = "SELECT id FROM `" . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . "`
80
- WHERE user_id = %d AND
81
- user_type = 'REGISTERED' AND abandoned_cart_info NOT LIKE '%$blank_cart_info%' AND abandoned_cart_info NOT LIKE '$blank_cart'";
82
-
83
- $cart_ids = $wpdb->get_results( $wpdb->prepare( $cart_query, $user_id ) );
84
- } else { // guest carts
85
- $guest_query = "SELECT id FROM `" . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite' . "`
86
- WHERE email_id = %s";
87
-
88
- $guest_user_ids = $wpdb->get_results( $wpdb->prepare( $guest_query, $email_address ) );
89
-
90
- if ( 0 == count( $guest_user_ids ) )
91
- return array(
92
- 'data' => array(),
93
- 'done' => true,
94
- );
95
-
96
- $cart_ids = array();
97
-
98
- foreach ( $guest_user_ids as $ids ) {
99
- // get the cart data
100
- $cart_query = "SELECT id, abandoned_cart_info AS cart_info FROM `" . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . "`
101
- WHERE user_id = %d AND
102
- user_type = 'GUEST'";
103
-
104
- $cart_data = $wpdb->get_results( $wpdb->prepare( $cart_query, $ids->id ) );
105
-
106
- $cart_ids = array_merge( $cart_ids, $cart_data );
107
- }
108
- }
109
-
110
- if ( 0 < count( $cart_ids ) ) {
111
-
112
- $cart_chunks = array_chunk( $cart_ids, 10, true );
113
-
114
- $cart_export = isset( $cart_chunks[ $page - 1 ] ) ? $cart_chunks[ $page - 1 ] : array();
115
- if ( count( $cart_export ) > 0 ) {
116
-
117
- foreach ( $cart_export as $abandoned_ids ) {
118
-
119
- $cart_id = $abandoned_ids->id;
120
- if ( count( $abandoned_ids->id ) > 0 ) {
121
- $data_to_export[] = array(
122
- 'group_id' => 'wcal_carts',
123
- 'group_label' => __( 'Abandoned Carts', 'woocommerce-abandoned-cart' ),
124
- 'item_id' => 'cart-' . $cart_id,
125
- 'data' => self::get_cart_data( $cart_id ),
126
- );
127
- }
128
- }
129
- $done = $page > count( $cart_chunks );
130
- } else {
131
- $done = true;
132
- }
133
- } else {
134
- $done = true;
135
- }
136
-
137
- return array(
138
- 'data' => $data_to_export,
139
- 'done' => $done,
140
- );
141
-
142
- }
143
-
144
- /**
145
- * Returns the personal data for each abandoned cart
146
- *
147
- * @param integer $abandoned_id - Abandoned Cart ID
148
- * @return array $personal_data - Personal data to be displayed
149
- * @global $wpdb
150
- * @since 4.9
151
- */
152
- static function get_cart_data( $abandoned_id ) {
153
- $personal_data = array();
154
-
155
- global $wpdb;
156
-
157
- $cart_query = "SELECT * FROM `" . $wpdb->prefix . 'ac_abandoned_cart_history_lite' . "`
158
- WHERE id = %d";
159
- $cart_details = $wpdb->get_results( $wpdb->prepare( $cart_query, $abandoned_id ) );
160
- $cart_details = $cart_details[0];
161
- $user_id = $cart_details->user_id;
162
- $user_type = $cart_details->user_type;
163
-
164
- if ( $user_type == 'GUEST' ) {
165
-
166
- $cart_details_to_export = apply_filters( 'wcal_personal_export_cart_details_prop', array(
167
- 'cart_id' => __( 'Abandoned Cart ID', 'woocommerce-abandoned-cart' ),
168
- 'date_created' => __( 'Abandoned Date', 'woocommerce-abandoned-cart' ),
169
- 'cart_status' => __( 'Abandoned Cart Status', 'woocommerce-abandoned-cart' ),
170
- 'total' => __( 'Cart Total', 'woocommerce-abandoned-cart' ),
171
- 'items' => __( 'Items Present', 'woocommerce-abandoned-cart' ),
172
- 'session_id' => __( 'Session ID', 'woocommerce-abandoned-cart' ),
173
- 'formatted_billing_address' => __( 'Billing Address', 'woocommerce-abandoned-cart' ),
174
- 'billing_email' => __( 'Email Address', 'woocommerce-abandoned-cart' ),
175
- ), $abandoned_id );
176
-
177
- } else {
178
- $cart_details_to_export = apply_filters( 'wcal_personal_export_cart_details_prop', array(
179
- 'cart_id' => __( 'Abandoned Cart ID', 'woocommerce-abandoned-cart' ),
180
- 'date_created' => __( 'Abandoned Date', 'woocommerce-abandoned-cart' ),
181
- 'cart_status' => __( 'Abandoned Cart Status', 'woocommerce-abandoned-cart' ),
182
- 'total' => __( 'Cart Total', 'woocommerce-abandoned-cart' ),
183
- 'items' => __( 'Items Present', 'woocommerce-abandoned-cart' ),
184
- 'formatted_billing_address' => __( 'Billing Address', 'woocommerce-abandoned-cart' ),
185
- 'billing_email' => __( 'Email Address', 'woocommerce-abandoned-cart' ),
186
- ), $abandoned_id );
187
-
188
- }
189
-
190
- $cart_data = json_decode( stripslashes( $cart_details->abandoned_cart_info ) );
191
- $cart_info = $cart_data->cart;
192
-
193
- if ( count( $cart_info ) > 0 ) {
194
- $cart_details_formatted = self::wcal_get_cart_details_export( $cart_info );
195
- }
196
-
197
- if ( 'GUEST' == $user_type ) {
198
- $guest_details = self::wcal_get_guest_personal_info( $user_id );
199
- }
200
- foreach ( $cart_details_to_export as $prop => $name ) {
201
-
202
- switch ( $prop ) {
203
- case 'cart_id':
204
- $value = $cart_details->id;
205
- break;
206
- case 'date_created':
207
- $value = date( 'Y-m-d H:i:s', $cart_details->abandoned_cart_time );
208
- break;
209
- case 'cart_status':
210
-
211
- $cart_ignored = $cart_details->cart_ignored;
212
-
213
- switch( $cart_ignored ) {
214
- case '0':
215
- $value = $cart_details->recovered_cart > 0 ? __( "Cart Recovered - Order #", 'woocommerce-abandoned-cart' ) . $cart_details->recovered_cart : __( 'Abandoned', 'woocommerce-abandoned-cart' );
216
- break;
217
- case '1':
218
- $value = $cart_details->recovered_cart > 0 ? __( "Cart Recovered - Order #", 'woocommerce-abandoned-cart' ) . $cart_details->recovered_cart : __( 'Abandoned but new cart created', 'woocommerce-abandoned-cart' );
219
- break;
220
- case '2':
221
- $value = __( 'Abandoned - Unpaid Order #', 'woocommerce-abandoned-cart') . $cart_details->recovered_cart;
222
- break;
223
- }
224
- break;
225
- case 'total':
226
- $total = 0;
227
-
228
- if ( count( $cart_info ) > 0 ) {
229
- foreach ( $cart_info as $k => $v ) {
230
-
231
- $total += $cart_details_formatted[$k][ 'item_total' ];
232
- }
233
- }
234
- $value = wc_price( $total );
235
- break;
236
- case 'items':
237
- $value = '';
238
-
239
- if ( count( $cart_info ) > 0 ) {
240
- foreach ( $cart_info as $k => $v ) {
241
-
242
- $product_name = $cart_details_formatted[$k][ 'product_name' ];
243
- $qty = $cart_details_formatted[$k][ 'qty' ];
244
-
245
- $value .= ( $value == '' ) ? "$product_name x $qty" : ", $product_name x $qty";
246
- }
247
- }
248
- break;
249
- case 'formatted_billing_address':
250
-
251
- if ( $user_type == 'REGISTERED' ) { // registered user
252
-
253
- $billing = wcal_common::wcal_get_billing_details( $user_id );
254
- $value = get_user_meta( $user_id, 'billing_first_name', true ); // First Name
255
- $value .= ' ' . get_user_meta( $user_id, 'billing_last_name', true ); // Last Name
256
- if ( count( $billing ) > 0 ) {
257
- foreach ( $billing as $details ) {
258
- if ( '' != $details ) {
259
- $value .= ",$details ";
260
- }
261
- }
262
-
263
- }
264
- } elseif ( 'GUEST' == $user_type ) {
265
- if ( count( $guest_details ) > 0 ) {
266
- $value = $guest_details->billing_first_name; // First Name
267
- $value .= ' ' . $guest_details->billing_last_name; // Last Name
268
- }
269
- }
270
- break;
271
-
272
- case 'billing_email':
273
- if ( 'REGISTERED' == $user_type ) { // registered user
274
- $value = get_user_meta( $user_id, $prop, true );
275
- } else if ( 'GUEST' == $user_type ) {
276
- if ( count( $guest_details ) > 0 ) {
277
- $value = $guest_details->$prop;
278
- }
279
- }
280
- break;
281
- default:
282
- $value = ( isset( $cart_details->$prop ) ) ? $cart_details->$prop : '';
283
- break;
284
- }
285
-
286
- $value = apply_filters( 'wcal_personal_export_cart_details_prop_value', $value, $prop, $cart_details );
287
-
288
- $personal_data[] = array(
289
- 'name' => $name,
290
- 'value' => $value,
291
- );
292
-
293
- }
294
- $personal_data = apply_filters( 'wcal_personal_data_cart_details_export', $personal_data, $cart_details );
295
-
296
- return $personal_data;
297
- }
298
-
299
- /**
300
- * Returns the personal data from the plugin guest cart table
301
- * for guest abandoned carts
302
- *
303
- * @param integer $user_id - User ID
304
- * @return array $guest_details - Guest personal details
305
- * @global $wpdb
306
- * @since 4.9
307
- */
308
- static function wcal_get_guest_personal_info( $user_id ) {
309
- global $wpdb;
310
- $guest_details = array();
311
-
312
- $guest_query = "SELECT billing_first_name, billing_last_name, email_id AS billing_email, phone AS billing_phone FROM `" . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite' . "`
313
- WHERE id = %d";
314
-
315
- $guest_details = $wpdb->get_results( $wpdb->prepare( $guest_query, $user_id ) );
316
-
317
- if ( is_array( $guest_details ) && count( $guest_details ) > 0 ) {
318
- $guest_details = $guest_details[0];
319
- }
320
-
321
- return $guest_details;
322
- }
323
-
324
- /**
325
- * Returns the Cart Details such as quantity, product name
326
- * etc.
327
- *
328
- * @param object $cart_info - Abandoned Cart Information
329
- * @return array $cart_details - Array containing product, qty & total for each item
330
- * @since 4.9
331
- */
332
- static function wcal_get_cart_details_export( $cart_info ) {
333
-
334
- $cart_details = array();
335
-
336
- if ( count( $cart_info ) > 0 ) {
337
-
338
- $cart_total = 0;
339
- foreach ( $cart_info as $k => $item_detail ) {
340
-
341
- // Qty
342
- $qty = $item_detail->quantity;
343
-
344
- //Product Name
345
- $product_id = $item_detail->product_id;
346
- $prod_obj = wc_get_product( $product_id );
347
- $product_name = $prod_obj->get_name();
348
-
349
- // Variation Name
350
- if ( isset( $item_detail->variation_id ) && $item_detail->variation_id > 0 ) {
351
- $variation_id = $item_detail->variation_id;
352
- $variation = wc_get_product( $variation_id );
353
- $variation_name = $variation->get_name();
354
-
355
- $product_name = $variation_name;
356
- }
357
-
358
- // Total
359
- $item_total = $item_detail->line_total;
360
- if ( $item_detail->line_subtotal_tax > 0 ) {
361
- $item_total += $item_detail->line_subtotal_tax;
362
- }
363
-
364
- // Populate the array
365
- $cart_details[ $k ][ 'qty' ] = $qty;
366
- $cart_details[ $k ][ 'product_name' ] = $product_name;
367
- $cart_details[ $k ][ 'item_total' ] = $item_total;
368
-
369
- $cart_total += $item_total;
370
- }
371
-
372
- $cart_details[ 'total' ] = $cart_total;
373
- }
374
-
375
- return $cart_details;
376
- }
377
- } // end of class
378
- $Wcal_Personal_Data_Export = new Wcal_Personal_Data_Export();
379
- } // end if
380
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/wcap_add_cart_popup_modal.php CHANGED
@@ -288,77 +288,6 @@ if ( ! class_exists( 'Wcap_Add_Cart_Popup_Modal' ) ) {
288
 
289
  }
290
 
291
- /**
292
-
293
- * It will Save the setting on the add to cart modal settings page.
294
-
295
- * @since 6.0
296
- */
297
-
298
- public static function wcap_add_to_cart_popup_save_settings() {
299
-
300
- if ( $_POST ['wcap_heading_section_text_email'] ) {
301
-
302
- update_option( 'wcap_heading_section_text_email', $_POST ['wcap_heading_section_text_email'] );
303
-
304
- }
305
-
306
- if ( $_POST ['wcap_popup_heading_color_picker'] ) {
307
-
308
- update_option( 'wcap_popup_heading_color_picker', $_POST ['wcap_popup_heading_color_picker'] );
309
-
310
- }
311
-
312
- if ( $_POST ['wcap_text_section_text'] ) {
313
-
314
- update_option( 'wcap_text_section_text', $_POST ['wcap_text_section_text'] );
315
-
316
- }
317
-
318
- if ( $_POST ['wcap_popup_text_color_picker'] ) {
319
-
320
- update_option( 'wcap_popup_text_color_picker', $_POST ['wcap_popup_text_color_picker'] );
321
-
322
- }
323
-
324
- if ( $_POST ['wcap_email_placeholder_section_input_text'] ) {
325
-
326
- update_option( 'wcap_email_placeholder_section_input_text', $_POST ['wcap_email_placeholder_section_input_text'] );
327
-
328
- }
329
-
330
- if ( $_POST ['wcap_button_section_input_text'] ) {
331
-
332
- update_option( 'wcap_button_section_input_text', $_POST ['wcap_button_section_input_text'] );
333
-
334
- }
335
-
336
- if ( $_POST ['wcap_button_color_picker'] ) {
337
-
338
- update_option( 'wcap_button_color_picker', $_POST ['wcap_button_color_picker'] );
339
-
340
- }
341
-
342
- if ( isset( $_POST ['wcap_button_text_color_picker'] ) ) {
343
-
344
- update_option( 'wcap_button_text_color_picker', $_POST ['wcap_button_text_color_picker'] );
345
-
346
- }
347
-
348
- if ( isset( $_POST ['wcap_non_mandatory_modal_section_fields_input_text'] ) ) {
349
-
350
- update_option( 'wcap_non_mandatory_text', $_POST ['wcap_non_mandatory_modal_section_fields_input_text'] );
351
-
352
- }
353
-
354
- $custom_pages = isset( $_POST['wcap_page_select'] ) ? $_POST['wcap_page_select'] : array();
355
-
356
- update_option( 'wcap_custom_pages_list', $custom_pages );
357
-
358
- }
359
-
360
-
361
-
362
  /**
363
 
364
  * It will add the setting for Heading section on the add to cart modal settings page.
288
 
289
  }
290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  /**
292
 
293
  * It will add the setting for Heading section on the add to cart modal settings page.
includes/admin/wcap_pro_settings.php CHANGED
@@ -3,849 +3,522 @@
3
  /**
4
 
5
  * Display all the settings in PRO
6
-
7
  *
8
-
9
  * @since 2.4
10
-
11
  */
12
 
13
  // Exit if accessed directly
14
 
15
- if ( ! defined( 'ABSPATH' ) ) exit;
16
-
17
-
18
-
19
- if ( ! class_exists('WCAP_Pro_Settings' ) ) {
20
-
21
-
22
-
23
- class WCAP_Pro_Settings {
24
-
25
-
26
-
27
- /**
28
-
29
- * Construct
30
-
31
- * @since 2.4
32
-
33
- */
34
-
35
- public function __construct() {
36
-
37
-
38
-
39
- add_action( 'admin_init', array( &$this, 'wcal_pro_settings' ) );
40
-
41
- add_action( 'wcal_add_new_settings', array(&$this, 'wcap_pro_general_settings' ) );
42
-
43
- }
44
-
45
-
46
-
47
- static function wcap_atc_settings() {
48
-
49
-
50
-
51
- wp_enqueue_style( 'wcap_modal_preview', WCAL_PLUGIN_URL . '/assets/css/admin/wcap_preview_modal.css' );
52
-
53
- wp_enqueue_style( 'wcap_add_to_cart_popup_modal', WCAL_PLUGIN_URL . '/assets/css/admin/wcap_add_to_cart_popup_modal.min.css' );
54
-
55
-
56
- $purchase_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=acupgradetopro&utm_medium=link&utm_campaign=AbandonCartLite';
57
-
58
- ?>
59
-
60
- <form method="post" action="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_atc_settings">
61
-
62
- <p style="font-size:15px;">
63
-
64
- <b><i><?php
65
- /* translators: %s Purchase Link */
66
- printf( __( "Upgrade to <a href='%s' target='_blank'>Abandoned Cart Pro for WooCommerce</a> to enable the feature.", 'woocommerce-abandoned-cart' ), $purchase_link);
67
- ?></i></b>
68
-
69
- </p>
70
-
71
- <?php Wcap_Add_Cart_Popup_Modal::wcap_add_to_cart_popup_settings(); ?>
72
-
73
- </form>
74
-
75
- <?php
76
-
77
- }
78
-
79
-
80
-
81
- static function wcap_fb_settings() {
82
-
83
- ?>
84
-
85
- <form method="post" action="options.php">
86
-
87
- <?php
88
-
89
- //settings_errors();
90
-
91
- settings_fields( 'woocommerce_fb_settings' );
92
-
93
- do_settings_sections( 'woocommerce_ac_fb_page' );
94
-
95
- submit_button( __( 'Save Changes', 'woocommerce-abandoned-cart' ), 'primary', 'submit', true, array( 'disabled' => 'disabled' ) );
96
-
97
- ?>
98
-
99
- </form>
100
-
101
- <?php
102
-
103
- }
104
-
105
-
106
-
107
- static function wcap_pro_general_settings() {
108
-
109
-
110
-
111
-
112
- $upgrade_pro_msg = '<br><b><i>Upgrade to <a href="https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=acupgradetopro&utm_medium=link&utm_campaign=AbandonCartLite" target="_blank">Abandoned Cart Pro for WooCommerce</a> to enable the setting.</i></b>';
113
-
114
- add_settings_field(
115
-
116
- 'ac_cart_abandoned_time_guest',
117
-
118
- __( 'Cart abandoned cut-off time for guest users', 'woocommerce-abandoned-cart' ),
119
-
120
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_cart_abandoned_time_guest_callback' ),
121
-
122
- 'woocommerce_ac_page',
123
-
124
- 'ac_lite_general_settings_section',
125
-
126
- array( __( "For guest users & visitors consider cart abandoned after X minutes of item being added to cart & order not placed.", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
127
-
128
- );
129
-
130
-
131
-
132
- add_settings_field(
133
-
134
- 'ac_disable_guest_cart_email',
135
-
136
- __( 'Do not track carts of guest users', 'woocommerce-abandoned-cart' ),
137
-
138
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_disable_guest_cart_email_callback' ),
139
-
140
- 'woocommerce_ac_page',
141
-
142
- 'ac_lite_general_settings_section',
143
-
144
- array( __( "Abandoned carts of guest users will not be tracked.", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
145
-
146
- );
147
-
148
-
149
-
150
- add_settings_field(
151
-
152
- 'ac_disable_logged_in_cart_email',
153
-
154
- __( 'Do not track carts of logged-in users', 'woocommerce-abandoned-cart' ),
155
-
156
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_disable_logged_in_cart_email_callback' ),
157
-
158
- 'woocommerce_ac_page',
159
-
160
- 'ac_lite_general_settings_section',
161
-
162
- array( __( "Abandoned carts of logged-in users will not be tracked.", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
163
-
164
- );
165
-
166
-
167
-
168
- add_settings_field(
169
-
170
- 'ac_capture_email_address_from_url',
171
-
172
- __( 'Capture Email address from URL', 'woocommerce-abandoned-cart' ),
173
-
174
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_capture_email_address_from_url' ),
175
-
176
- 'woocommerce_ac_page',
177
-
178
- 'ac_lite_general_settings_section',
179
-
180
- array( __( "If your site URL contain the same key, then it will capture it as an email address of customer.", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
181
-
182
- );
183
-
184
-
185
-
186
- register_setting(
187
-
188
- 'woocommerce_ac_settings',
189
-
190
- 'ac_enable_cart_emails'
191
-
192
- );
193
-
194
-
195
-
196
- register_setting(
197
-
198
- 'woocommerce_ac_settings',
199
-
200
- 'ac_cart_abandoned_time_guest'
201
-
202
- );
203
-
204
-
205
-
206
- register_setting(
207
-
208
- 'woocommerce_ac_settings',
209
-
210
- 'ac_disable_guest_cart_email'
211
-
212
- );
213
-
214
- register_setting(
215
-
216
- 'woocommerce_ac_settings',
217
-
218
- 'ac_disable_logged_in_cart_email'
219
-
220
- );
221
-
222
-
223
-
224
- register_setting(
225
-
226
- 'woocommerce_ac_settings',
227
-
228
- 'ac_capture_email_address_from_url'
229
-
230
- );
231
-
232
-
233
-
234
- add_settings_field(
235
-
236
- 'wcap_product_image_size',
237
-
238
- __( 'Product Image( H x W )', 'woocommerce-abandoned-cart' ),
239
-
240
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_product_image_size_callback' ),
241
-
242
- 'woocommerce_ac_email_page',
243
-
244
- 'ac_email_settings_section',
245
-
246
- array( __( "This setting affects the dimension of the product image in the abandoned cart reminder email.", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
247
-
248
- );
249
-
250
-
251
-
252
- register_setting(
253
-
254
- 'ac_email_settings_section',
255
-
256
- 'wcap_product_image_size'
257
-
258
- );
259
-
260
-
261
-
262
- add_settings_section(
263
-
264
- 'ac_cron_job_settings_section', // ID used to identify this section and with which to register options
265
-
266
- __( 'Setting for sending Emails & SMS using Action Scheduler', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page
267
-
268
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_cron_job_callback' ),// Callback used to render the description of the section
269
-
270
- 'woocommerce_ac_page' // Page on which to add this section of options
271
-
272
- );
273
-
274
-
275
-
276
- add_settings_field(
277
-
278
- 'wcap_use_auto_cron',
279
-
280
- __( 'Send Abandoned cart emails automatically using Action Scheduler', 'woocommerce-abandoned-cart' ),
281
-
282
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_use_auto_cron_callback' ),
283
-
284
- 'woocommerce_ac_page',
285
-
286
- 'ac_cron_job_settings_section',
287
-
288
- array( __( "Enabling this setting will send the abandoned cart reminder emails to the customer after the set time. If disabled, abandoned cart reminder emails will not be sent using the Action Scheduler. You will need to set cron job manually from cPanel. If you are unsure how to set the cron job, please <a href= mailto:support@tychesoftwares.com>contact us</a> for it.", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
289
-
290
- );
291
-
292
-
293
-
294
- add_settings_field(
295
-
296
- 'wcap_cron_time_duration',
297
-
298
- __( 'Run automated Scheduler every X minutes', 'woocommerce-abandoned-cart' ),
299
-
300
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_cron_time_duration_callback' ),
301
-
302
- 'woocommerce_ac_page',
303
-
304
- 'ac_cron_job_settings_section',
305
-
306
- array( __( "The duration in minutes after which an action should be automatically scheduled to send email, SMS & FB reminders to customers.", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
307
-
308
- );
309
-
310
-
311
-
312
- add_settings_section(
313
-
314
- 'ac_restrict_settings_section', // ID used to identify this section and with which to register options
315
-
316
- __( 'Rules to exclude capturing abandoned carts', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page
317
-
318
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_custom_restrict_callback' ),// Callback used to render the description of the section
319
-
320
- 'woocommerce_ac_page' // Page on which to add this section of options
321
-
322
- );
323
-
324
-
325
-
326
- add_settings_field(
327
-
328
- 'wcap_restrict_ip_address',
329
-
330
- __( 'Do not capture abandoned carts for these IP addresses', 'woocommerce-abandoned-cart' ),
331
-
332
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_restrict_ip_address_callback' ),
333
-
334
- 'woocommerce_ac_page',
335
-
336
- 'ac_restrict_settings_section',
337
-
338
- array( __( "The carts abandoned from these IP addresses will not be tracked by the plugin. Accepts wildcards, e.g <code>192.168.*</code> will block all IP addresses which starts from \"192.168\". <i>Separate IP addresses with commas.</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
339
-
340
- );
341
-
342
-
343
-
344
- add_settings_field(
345
-
346
- 'wcap_restrict_email_address',
347
-
348
- __( 'Do not capture abandoned carts for these email addresses', 'woocommerce-abandoned-cart' ),
349
-
350
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_restrict_email_address_callback' ),
351
-
352
- 'woocommerce_ac_page',
353
-
354
- 'ac_restrict_settings_section',
355
-
356
- array( __( "The carts abandoned using these email addresses will not be tracked by the plugin. <i>Separate email addresses with commas.</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
357
-
358
- );
359
-
360
-
361
-
362
- add_settings_field(
363
-
364
- 'wcap_restrict_domain_address',
365
-
366
- __( 'Do not capture abandoned carts for email addresses from these domains', 'woocommerce-abandoned-cart' ),
367
-
368
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_restrict_domain_address_callback' ),
369
-
370
- 'woocommerce_ac_page',
371
-
372
- 'ac_restrict_settings_section',
373
-
374
- array( __( "The carts abandoned from email addresses with these domains will not be tracked by the plugin. <i>Separate email address domains with commas.</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
375
-
376
- );
377
-
378
-
379
-
380
-
381
-
382
- }
383
-
384
- static function wcap_sms_settings() {
385
- ?>
386
-
387
- <form method="post" action="options.php">
388
-
389
- <?php
390
-
391
- settings_fields ( 'woocommerce_sms_settings' );
392
-
393
- do_settings_sections( 'woocommerce_ac_sms_page' );
394
-
395
- submit_button( __( 'Save Changes', 'woocommerce-abandoned-cart' ), 'primary', 'submit', true, array( 'disabled' => 'disabled' ) );
396
-
397
- ?>
398
-
399
- </form>
400
-
401
- <div id="test_fields">
402
-
403
- <h2><?php _e( 'Send Test SMS', 'woocommerce-abandoned-cart' ); ?></h2>
404
-
405
- <div id="status_msg" style="background: white;border-left: #6389DA 4px solid;padding: 10px;display: none;width: 90%;"></div>
406
-
407
- <table class="form-table">
408
-
409
- <tr>
410
-
411
- <th><?php _e( 'Recipient', 'woocommerce-abandoned-cart' ); ?></th>
412
-
413
- <td>
414
-
415
- <input id="test_number" name="test_number" type=text readonly />
416
-
417
- <i><?php _e( 'Must be a valid phone number in E.164 format.', 'woocommerce-abandoned-cart' );?></i>
418
-
419
- </td>
420
-
421
- </tr>
422
-
423
- <tr>
424
-
425
- <th><?php _e( 'Message', 'woocommerce-abandoned-cart' );?></th>
426
-
427
- <td><textarea id="test_msg" rows="4" cols="70" readonly ><?php _e( 'Hello World!', 'woocommerce-abandoned-cart' );?></textarea></td>
428
-
429
- </tr>
430
-
431
- <tr>
432
-
433
- <td colspan="2"><input type="button" id="wcap_test_sms" class="button-primary" value="<?php _e( 'Send', 'wocommerce-ac' );?>" /></td>
434
-
435
- </tr>
436
-
437
- </table>
438
-
439
- </div>
440
-
441
- <?php
442
-
443
- }
444
-
445
-
446
-
447
- function wcal_pro_settings() {
448
-
449
-
450
-
451
- $upgrade_pro_msg = '<br><b><i>Upgrade to <a href="https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=acupgradetopro&utm_medium=link&utm_campaign=AbandonCartLite" target="_blank">Abandoned Cart Pro for WooCommerce</a> to enable the setting.</i></b>';
452
-
453
- /**
454
-
455
- * New Settings for SMS Notifications
456
-
457
- */
458
-
459
- add_settings_section(
460
-
461
- 'wcap_sms_settings_section', // ID used to identify this section and with which to register options
462
-
463
- __( 'Twilio', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page
464
-
465
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_sms_settings_section_callback' ), // Callback used to render the description of the section
466
-
467
- 'woocommerce_ac_sms_page' // Page on which to add this section of options
468
-
469
- );
470
-
471
-
472
-
473
- add_settings_field(
474
-
475
- 'wcap_enable_sms_reminders',
476
-
477
- __( 'Enable SMS', 'woocommerce-abandoned-cart' ),
478
-
479
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_enable_sms_reminders_callback' ),
480
-
481
- 'woocommerce_ac_sms_page',
482
-
483
- 'wcap_sms_settings_section',
484
-
485
- array( __( "<i>Enable the ability to send reminder SMS for abandoned carts.</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
486
-
487
- );
488
-
489
-
490
-
491
- add_settings_field(
492
-
493
- 'wcap_sms_from_phone',
494
-
495
- __( 'From', 'woocommerce-abandoned-cart' ),
496
-
497
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_sms_from_phone_callback' ),
498
-
499
- 'woocommerce_ac_sms_page',
500
-
501
- 'wcap_sms_settings_section',
502
-
503
- array( __( "<i>Must be a Twilio phone number (in E.164 format) or alphanumeric sender ID.</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
504
-
505
- );
506
-
507
-
508
-
509
- add_settings_field(
510
-
511
- 'wcap_sms_account_sid',
512
-
513
- __( 'Account SID', 'woocommerce-abandoned-cart' ),
514
-
515
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_sms_account_sid_callback' ),
516
-
517
- 'woocommerce_ac_sms_page',
518
-
519
- 'wcap_sms_settings_section',
520
-
521
- array( $upgrade_pro_msg )
522
-
523
- );
524
-
525
-
526
-
527
- add_settings_field(
528
-
529
- 'wcap_sms_auth_token',
530
-
531
- __( 'Auth Token', 'woocommerce-abandoned-cart' ),
532
-
533
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_sms_auth_token_callback' ),
534
-
535
- 'woocommerce_ac_sms_page',
536
-
537
- 'wcap_sms_settings_section',
538
-
539
- array( $upgrade_pro_msg )
540
-
541
- );
542
-
543
-
544
-
545
-
546
-
547
- register_setting(
548
-
549
- 'woocommerce_sms_settings',
550
-
551
- 'wcap_enable_sms_reminders'
552
-
553
- );
554
-
555
-
556
-
557
- register_setting(
558
-
559
- 'woocommerce_sms_settings',
560
-
561
- 'wcap_sms_from_phone'
562
-
563
- );
564
-
565
-
566
-
567
- register_setting(
568
-
569
- 'woocommerce_sms_settings',
570
-
571
- 'wcap_sms_account_sid'
572
-
573
- );
574
-
575
-
576
-
577
- register_setting(
578
-
579
- 'woocommerce_sms_settings',
580
-
581
- 'wcap_sms_auth_token'
582
-
583
- );
584
-
585
-
586
-
587
- add_settings_section(
588
-
589
- 'wcap_fb_settings_section',
590
-
591
- __( 'Facebook Messenger Settings', 'woocommerce-abandoned-cart' ),
592
-
593
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_description' ),
594
-
595
- 'woocommerce_ac_fb_page'
596
-
597
- );
598
-
599
-
600
-
601
- add_settings_field(
602
-
603
- 'wcap_enable_fb_reminders',
604
-
605
- __( 'Enable Facebook Messenger Reminders', 'woocommerce-abandoned-cart' ),
606
-
607
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_checkbox_callback' ),
608
-
609
- 'woocommerce_ac_fb_page',
610
-
611
- 'wcap_fb_settings_section',
612
-
613
- array( __( "<i>This option will display a checkbox after the Add to cart button for user consent to connect with Facebook.</i>", 'woocommerce-abandoned-cart', 'wcap_enable_fb_reminders' ) . $upgrade_pro_msg )
614
-
615
- );
616
-
617
-
618
-
619
- add_settings_field(
620
-
621
- 'wcap_enable_fb_reminders_popup',
622
-
623
- __( 'Facebook Messenger on Add to Cart Pop-up modal', 'woocommerce-abandoned-cart' ),
624
-
625
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_checkbox_callback' ),
626
-
627
- 'woocommerce_ac_fb_page',
628
-
629
- 'wcap_fb_settings_section',
630
-
631
- array( __( "<i>This option will display a checkbox on the pop-up modal to connect with Facebook.</i>", 'woocommerce-abandoned-cart', 'wcap_enable_fb_reminders_popup' ) . $upgrade_pro_msg )
632
-
633
- );
634
-
635
-
636
-
637
- add_settings_field(
638
-
639
- 'wcap_fb_user_icon',
640
-
641
- __( 'Icon size of user', 'woocommerce-abandoned-cart' ),
642
-
643
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_dropdown_callback' ),
644
-
645
- 'woocommerce_ac_fb_page',
646
-
647
- 'wcap_fb_settings_section',
648
-
649
- array(
650
-
651
- __( "<i>Select the size of user icon which shall be displayed below the checkbox in case the user is logged in.</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg,
652
 
653
- 'wcap_fb_user_icon',
654
 
655
- array(
656
 
657
- 'small' => __( 'Small', 'woocommerce-abandoned-cart' ),
658
 
659
- 'medium' => __( 'Medium', 'woocommerce-abandoned-cart' ),
660
 
661
- 'large' => __( 'Large', 'woocommerce-abandoned-cart' ),
662
 
663
- 'standard' => __( 'Standard', 'woocommerce-abandoned-cart' ),
664
 
665
- 'xlarge' => __( 'Extra Large', 'woocommerce-abandoned-cart' )
666
 
667
- )
668
 
669
- )
670
 
671
- );
672
 
 
 
673
 
 
674
 
675
- add_settings_field(
676
 
677
- 'wcap_fb_consent_text',
678
 
679
- __( 'Consent text', 'woocommerce-abandoned-cart' ),
680
 
681
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
682
 
683
- 'woocommerce_ac_fb_page',
684
 
685
- 'wcap_fb_settings_section',
686
 
687
- array( __( "<i>Text that will appear above the consent checkbox. HTML tags are also allowed.</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_consent_text' )
688
 
689
- );
690
 
 
691
 
 
692
 
693
- add_settings_field(
694
 
695
- 'wcap_fb_page_id',
696
 
697
- __( 'Facebook Page ID', 'woocommerce-abandoned-cart' ),
 
 
 
 
 
698
 
699
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
700
 
701
- 'woocommerce_ac_fb_page',
702
 
703
- 'wcap_fb_settings_section',
704
 
705
- array( __( "<i>Facebook Page ID in numberic format. You can find your page ID from <a href='https://www.tychesoftwares.com/docs/docs/abandoned-cart-pro-for-woocommerce/send-abandoned-cart-reminder-notifications-using-facebook-messenger#fbpageid' target='_blank'>here</a></i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_page_id' )
706
 
707
- );
708
 
709
 
710
 
711
- add_settings_field(
712
 
713
- 'wcap_fb_app_id',
714
 
715
- __( 'Messenger App ID', 'woocommerce-abandoned-cart' ),
716
 
717
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
718
 
719
- 'woocommerce_ac_fb_page',
720
 
721
- 'wcap_fb_settings_section',
722
 
723
- array( __( "<i>Enter your Messenger App ID</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_app_id' )
724
 
725
- );
726
 
 
727
 
 
728
 
729
- add_settings_field(
730
 
731
- 'wcap_fb_page_token',
732
 
733
- __( 'Facebook Page Token', 'woocommerce-abandoned-cart' ),
734
 
735
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
736
 
737
- 'woocommerce_ac_fb_page',
738
 
739
- 'wcap_fb_settings_section',
740
 
741
- array( __( "<i>Enter your Facebook Page Token</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_page_token' )
 
 
 
 
 
 
 
742
 
743
- );
 
 
 
 
 
 
 
744
 
 
 
 
 
 
 
 
 
745
 
 
 
 
 
 
 
 
 
746
 
747
- add_settings_field(
 
 
 
748
 
749
- 'wcap_fb_verify_token',
 
 
 
750
 
751
- __( 'Verify Token', 'woocommerce-abandoned-cart' ),
 
 
 
752
 
753
- array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
 
 
 
754
 
755
- 'woocommerce_ac_fb_page',
 
 
 
756
 
757
- 'wcap_fb_settings_section',
 
 
 
 
 
 
 
758
 
759
- array( __( "<i>Enter your Verify Token</i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_verify_token' )
 
 
 
760
 
761
- );
 
 
 
 
 
762
 
 
 
 
 
 
 
 
 
763
 
 
 
 
 
 
 
 
 
764
 
765
- register_setting(
 
 
 
 
 
766
 
767
- 'woocommerce_fb_settings',
 
 
 
 
 
 
 
768
 
769
- 'wcap_enable_fb_reminders'
 
 
 
 
 
 
 
770
 
771
- );
 
 
 
 
 
 
 
772
 
 
773
 
 
 
774
 
775
- register_setting(
776
 
777
- 'woocommerce_fb_settings',
778
 
779
- 'wcap_enable_fb_reminders_popup'
780
 
781
- );
782
 
 
783
 
 
784
 
785
- register_setting(
786
 
787
- 'woocommerce_fb_settings',
788
 
789
- 'wcap_fb_consent_text'
790
 
791
- );
792
 
 
793
 
 
794
 
795
- register_setting(
796
 
797
- 'woocommerce_fb_settings',
798
 
799
- 'wcap_fb_page_id'
800
 
801
- );
802
 
 
803
 
 
804
 
805
- register_setting(
806
 
807
- 'woocommerce_fb_settings',
808
 
809
- 'wcap_fb_user_icon'
810
 
811
- );
812
 
 
813
 
 
814
 
815
- register_setting(
816
 
817
- 'woocommerce_fb_settings',
818
 
819
- 'wcap_fb_app_id'
820
 
821
- );
822
 
 
823
 
824
 
825
- register_setting(
826
 
827
- 'woocommerce_fb_settings',
828
 
829
- 'wcap_fb_page_token'
830
 
831
- );
832
 
 
 
833
 
 
 
 
 
 
 
834
 
835
- register_setting(
 
 
 
 
 
 
 
836
 
837
- 'woocommerce_fb_settings',
 
 
 
 
 
 
 
838
 
839
- 'wcap_fb_verify_token'
 
 
 
 
 
 
 
840
 
841
- );
 
 
 
 
 
 
 
842
 
843
- }
 
 
 
844
 
845
- } // end of class
 
 
 
846
 
847
- $WCAP_Pro_Settings = new WCAP_Pro_Settings();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
848
 
849
  } // end if
850
 
851
- ?>
3
  /**
4
 
5
  * Display all the settings in PRO
 
6
  *
 
7
  * @since 2.4
 
8
  */
9
 
10
  // Exit if accessed directly
11
 
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
 
16
 
 
17
 
18
+ if ( ! class_exists( 'WCAP_Pro_Settings' ) ) {
19
 
 
20
 
 
21
 
22
+ class WCAP_Pro_Settings {
23
 
 
24
 
 
25
 
26
+ /**
27
 
28
+ * Construct
29
 
30
+ * @since 2.4
31
+ */
32
 
33
+ public function __construct() {
34
 
35
+ add_action( 'admin_init', array( &$this, 'wcal_pro_settings' ) );
36
 
37
+ add_action( 'wcal_add_new_settings', array( &$this, 'wcap_pro_general_settings' ) );
38
 
39
+ }
40
 
 
41
 
 
42
 
43
+ static function wcap_atc_settings() {
44
 
45
+ wp_enqueue_style( 'wcap_modal_preview', WCAL_PLUGIN_URL . '/assets/css/admin/wcap_preview_modal.css' );
46
 
47
+ wp_enqueue_style( 'wcap_add_to_cart_popup_modal', WCAL_PLUGIN_URL . '/assets/css/admin/wcap_add_to_cart_popup_modal.min.css' );
48
 
49
+ $purchase_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=acupgradetopro&utm_medium=link&utm_campaign=AbandonCartLite';
50
 
51
+ ?>
52
 
53
+ <form method="post" action="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_atc_settings">
54
 
55
+ <p style="font-size:15px;">
56
 
57
+ <b><i>
58
+ <?php
59
+ /* translators: %s Purchase Link */
60
+ printf( __( "Upgrade to <a href='%s' target='_blank'>Abandoned Cart Pro for WooCommerce</a> to enable the feature.", 'woocommerce-abandoned-cart' ), $purchase_link );
61
+ ?>
62
+ </i></b>
63
 
64
+ </p>
65
 
66
+ <?php Wcap_Add_Cart_Popup_Modal::wcap_add_to_cart_popup_settings(); ?>
67
 
68
+ </form>
69
 
70
+ <?php
71
 
72
+ }
73
 
74
 
75
 
76
+ static function wcap_fb_settings() {
77
 
78
+ ?>
79
 
80
+ <form method="post" action="options.php">
81
 
82
+ <?php
83
 
84
+ // settings_errors();
85
 
86
+ settings_fields( 'woocommerce_fb_settings' );
87
 
88
+ do_settings_sections( 'woocommerce_ac_fb_page' );
89
 
90
+ submit_button( __( 'Save Changes', 'woocommerce-abandoned-cart' ), 'primary', 'submit', true, array( 'disabled' => 'disabled' ) );
91
 
92
+ ?>
93
 
94
+ </form>
95
 
96
+ <?php
97
 
98
+ }
99
 
 
100
 
 
101
 
102
+ static function wcap_pro_general_settings() {
103
 
104
+ $upgrade_pro_msg = '<br><b><i>Upgrade to <a href="https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=acupgradetopro&utm_medium=link&utm_campaign=AbandonCartLite" target="_blank">Abandoned Cart Pro for WooCommerce</a> to enable the setting.</i></b>';
105
 
106
+ add_settings_field(
107
+ 'ac_cart_abandoned_time_guest',
108
+ __( 'Cart abandoned cut-off time for guest users', 'woocommerce-abandoned-cart' ),
109
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_cart_abandoned_time_guest_callback' ),
110
+ 'woocommerce_ac_page',
111
+ 'ac_lite_general_settings_section',
112
+ array( __( 'For guest users & visitors consider cart abandoned after X minutes of item being added to cart & order not placed.', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
113
+ );
114
 
115
+ add_settings_field(
116
+ 'ac_disable_guest_cart_email',
117
+ __( 'Do not track carts of guest users', 'woocommerce-abandoned-cart' ),
118
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_disable_guest_cart_email_callback' ),
119
+ 'woocommerce_ac_page',
120
+ 'ac_lite_general_settings_section',
121
+ array( __( 'Abandoned carts of guest users will not be tracked.', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
122
+ );
123
 
124
+ add_settings_field(
125
+ 'ac_disable_logged_in_cart_email',
126
+ __( 'Do not track carts of logged-in users', 'woocommerce-abandoned-cart' ),
127
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_disable_logged_in_cart_email_callback' ),
128
+ 'woocommerce_ac_page',
129
+ 'ac_lite_general_settings_section',
130
+ array( __( 'Abandoned carts of logged-in users will not be tracked.', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
131
+ );
132
 
133
+ add_settings_field(
134
+ 'ac_capture_email_address_from_url',
135
+ __( 'Capture Email address from URL', 'woocommerce-abandoned-cart' ),
136
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_capture_email_address_from_url' ),
137
+ 'woocommerce_ac_page',
138
+ 'ac_lite_general_settings_section',
139
+ array( __( 'If your site URL contain the same key, then it will capture it as an email address of customer.', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
140
+ );
141
 
142
+ register_setting(
143
+ 'woocommerce_ac_settings',
144
+ 'ac_enable_cart_emails'
145
+ );
146
 
147
+ register_setting(
148
+ 'woocommerce_ac_settings',
149
+ 'ac_cart_abandoned_time_guest'
150
+ );
151
 
152
+ register_setting(
153
+ 'woocommerce_ac_settings',
154
+ 'ac_disable_guest_cart_email'
155
+ );
156
 
157
+ register_setting(
158
+ 'woocommerce_ac_settings',
159
+ 'ac_disable_logged_in_cart_email'
160
+ );
161
 
162
+ register_setting(
163
+ 'woocommerce_ac_settings',
164
+ 'ac_capture_email_address_from_url'
165
+ );
166
 
167
+ add_settings_field(
168
+ 'wcap_product_image_size',
169
+ __( 'Product Image( H x W )', 'woocommerce-abandoned-cart' ),
170
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_product_image_size_callback' ),
171
+ 'woocommerce_ac_email_page',
172
+ 'ac_email_settings_section',
173
+ array( __( 'This setting affects the dimension of the product image in the abandoned cart reminder email.', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
174
+ );
175
 
176
+ register_setting(
177
+ 'ac_email_settings_section',
178
+ 'wcap_product_image_size'
179
+ );
180
 
181
+ add_settings_section(
182
+ 'ac_cron_job_settings_section', // ID used to identify this section and with which to register options
183
+ __( 'Setting for sending Emails & SMS using Action Scheduler', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page
184
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_cron_job_callback' ), // Callback used to render the description of the section
185
+ 'woocommerce_ac_page' // Page on which to add this section of options
186
+ );
187
 
188
+ add_settings_field(
189
+ 'wcap_use_auto_cron',
190
+ __( 'Send Abandoned cart emails automatically using Action Scheduler', 'woocommerce-abandoned-cart' ),
191
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_use_auto_cron_callback' ),
192
+ 'woocommerce_ac_page',
193
+ 'ac_cron_job_settings_section',
194
+ array( __( 'Enabling this setting will send the abandoned cart reminder emails to the customer after the set time. If disabled, abandoned cart reminder emails will not be sent using the Action Scheduler. You will need to set cron job manually from cPanel. If you are unsure how to set the cron job, please <a href= mailto:support@tychesoftwares.com>contact us</a> for it.', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
195
+ );
196
 
197
+ add_settings_field(
198
+ 'wcap_cron_time_duration',
199
+ __( 'Run automated Scheduler every X minutes', 'woocommerce-abandoned-cart' ),
200
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_cron_time_duration_callback' ),
201
+ 'woocommerce_ac_page',
202
+ 'ac_cron_job_settings_section',
203
+ array( __( 'The duration in minutes after which an action should be automatically scheduled to send email, SMS & FB reminders to customers.', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
204
+ );
205
 
206
+ add_settings_section(
207
+ 'ac_restrict_settings_section', // ID used to identify this section and with which to register options
208
+ __( 'Rules to exclude capturing abandoned carts', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page
209
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_custom_restrict_callback' ), // Callback used to render the description of the section
210
+ 'woocommerce_ac_page' // Page on which to add this section of options
211
+ );
212
 
213
+ add_settings_field(
214
+ 'wcap_restrict_ip_address',
215
+ __( 'Do not capture abandoned carts for these IP addresses', 'woocommerce-abandoned-cart' ),
216
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_restrict_ip_address_callback' ),
217
+ 'woocommerce_ac_page',
218
+ 'ac_restrict_settings_section',
219
+ array( __( 'The carts abandoned from these IP addresses will not be tracked by the plugin. Accepts wildcards, e.g <code>192.168.*</code> will block all IP addresses which starts from "192.168". <i>Separate IP addresses with commas.</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
220
+ );
221
 
222
+ add_settings_field(
223
+ 'wcap_restrict_email_address',
224
+ __( 'Do not capture abandoned carts for these email addresses', 'woocommerce-abandoned-cart' ),
225
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_restrict_email_address_callback' ),
226
+ 'woocommerce_ac_page',
227
+ 'ac_restrict_settings_section',
228
+ array( __( 'The carts abandoned using these email addresses will not be tracked by the plugin. <i>Separate email addresses with commas.</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
229
+ );
230
 
231
+ add_settings_field(
232
+ 'wcap_restrict_domain_address',
233
+ __( 'Do not capture abandoned carts for email addresses from these domains', 'woocommerce-abandoned-cart' ),
234
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_restrict_domain_address_callback' ),
235
+ 'woocommerce_ac_page',
236
+ 'ac_restrict_settings_section',
237
+ array( __( 'The carts abandoned from email addresses with these domains will not be tracked by the plugin. <i>Separate email address domains with commas.</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
238
+ );
239
 
240
+ }
241
 
242
+ static function wcap_sms_settings() {
243
+ ?>
244
 
245
+ <form method="post" action="options.php">
246
 
247
+ <?php
248
 
249
+ settings_fields( 'woocommerce_sms_settings' );
250
 
251
+ do_settings_sections( 'woocommerce_ac_sms_page' );
252
 
253
+ submit_button( __( 'Save Changes', 'woocommerce-abandoned-cart' ), 'primary', 'submit', true, array( 'disabled' => 'disabled' ) );
254
 
255
+ ?>
256
 
257
+ </form>
258
 
259
+ <div id="test_fields">
260
 
261
+ <h2><?php _e( 'Send Test SMS', 'woocommerce-abandoned-cart' ); ?></h2>
262
 
263
+ <div id="status_msg" style="background: white;border-left: #6389DA 4px solid;padding: 10px;display: none;width: 90%;"></div>
264
 
265
+ <table class="form-table">
266
 
267
+ <tr>
268
 
269
+ <th><?php _e( 'Recipient', 'woocommerce-abandoned-cart' ); ?></th>
270
 
271
+ <td>
272
 
273
+ <input id="test_number" name="test_number" type=text readonly />
274
 
275
+ <i><?php _e( 'Must be a valid phone number in E.164 format.', 'woocommerce-abandoned-cart' ); ?></i>
276
 
277
+ </td>
278
 
279
+ </tr>
280
 
281
+ <tr>
282
 
283
+ <th><?php _e( 'Message', 'woocommerce-abandoned-cart' ); ?></th>
284
 
285
+ <td><textarea id="test_msg" rows="4" cols="70" readonly ><?php _e( 'Hello World!', 'woocommerce-abandoned-cart' ); ?></textarea></td>
286
 
287
+ </tr>
288
 
289
+ <tr>
290
 
291
+ <td colspan="2"><input type="button" id="wcap_test_sms" class="button-primary" value="<?php _e( 'Send', 'wocommerce-ac' ); ?>" /></td>
292
 
293
+ </tr>
294
 
295
+ </table>
296
 
297
+ </div>
298
 
299
+ <?php
300
 
301
+ }
302
 
303
 
 
304
 
305
+ function wcal_pro_settings() {
306
 
307
+ $upgrade_pro_msg = '<br><b><i>Upgrade to <a href="https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=acupgradetopro&utm_medium=link&utm_campaign=AbandonCartLite" target="_blank">Abandoned Cart Pro for WooCommerce</a> to enable the setting.</i></b>';
308
 
309
+ /**
310
 
311
+ * New Settings for SMS Notifications
312
+ */
313
 
314
+ add_settings_section(
315
+ 'wcap_sms_settings_section', // ID used to identify this section and with which to register options
316
+ __( 'Twilio', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page
317
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_sms_settings_section_callback' ), // Callback used to render the description of the section
318
+ 'woocommerce_ac_sms_page' // Page on which to add this section of options
319
+ );
320
 
321
+ add_settings_field(
322
+ 'wcap_enable_sms_reminders',
323
+ __( 'Enable SMS', 'woocommerce-abandoned-cart' ),
324
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_enable_sms_reminders_callback' ),
325
+ 'woocommerce_ac_sms_page',
326
+ 'wcap_sms_settings_section',
327
+ array( __( '<i>Enable the ability to send reminder SMS for abandoned carts.</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
328
+ );
329
 
330
+ add_settings_field(
331
+ 'wcap_sms_from_phone',
332
+ __( 'From', 'woocommerce-abandoned-cart' ),
333
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_sms_from_phone_callback' ),
334
+ 'woocommerce_ac_sms_page',
335
+ 'wcap_sms_settings_section',
336
+ array( __( '<i>Must be a Twilio phone number (in E.164 format) or alphanumeric sender ID.</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg )
337
+ );
338
 
339
+ add_settings_field(
340
+ 'wcap_sms_account_sid',
341
+ __( 'Account SID', 'woocommerce-abandoned-cart' ),
342
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_sms_account_sid_callback' ),
343
+ 'woocommerce_ac_sms_page',
344
+ 'wcap_sms_settings_section',
345
+ array( $upgrade_pro_msg )
346
+ );
347
 
348
+ add_settings_field(
349
+ 'wcap_sms_auth_token',
350
+ __( 'Auth Token', 'woocommerce-abandoned-cart' ),
351
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_sms_auth_token_callback' ),
352
+ 'woocommerce_ac_sms_page',
353
+ 'wcap_sms_settings_section',
354
+ array( $upgrade_pro_msg )
355
+ );
356
 
357
+ register_setting(
358
+ 'woocommerce_sms_settings',
359
+ 'wcap_enable_sms_reminders'
360
+ );
361
 
362
+ register_setting(
363
+ 'woocommerce_sms_settings',
364
+ 'wcap_sms_from_phone'
365
+ );
366
 
367
+ register_setting(
368
+ 'woocommerce_sms_settings',
369
+ 'wcap_sms_account_sid'
370
+ );
371
+
372
+ register_setting(
373
+ 'woocommerce_sms_settings',
374
+ 'wcap_sms_auth_token'
375
+ );
376
+
377
+ add_settings_section(
378
+ 'wcap_fb_settings_section',
379
+ __( 'Facebook Messenger Settings', 'woocommerce-abandoned-cart' ),
380
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_description' ),
381
+ 'woocommerce_ac_fb_page'
382
+ );
383
+
384
+ add_settings_field(
385
+ 'wcap_enable_fb_reminders',
386
+ __( 'Enable Facebook Messenger Reminders', 'woocommerce-abandoned-cart' ),
387
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_checkbox_callback' ),
388
+ 'woocommerce_ac_fb_page',
389
+ 'wcap_fb_settings_section',
390
+ array( __( '<i>This option will display a checkbox after the Add to cart button for user consent to connect with Facebook.</i>', 'woocommerce-abandoned-cart', 'wcap_enable_fb_reminders' ) . $upgrade_pro_msg )
391
+ );
392
+
393
+ add_settings_field(
394
+ 'wcap_enable_fb_reminders_popup',
395
+ __( 'Facebook Messenger on Add to Cart Pop-up modal', 'woocommerce-abandoned-cart' ),
396
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_checkbox_callback' ),
397
+ 'woocommerce_ac_fb_page',
398
+ 'wcap_fb_settings_section',
399
+ array( __( '<i>This option will display a checkbox on the pop-up modal to connect with Facebook.</i>', 'woocommerce-abandoned-cart', 'wcap_enable_fb_reminders_popup' ) . $upgrade_pro_msg )
400
+ );
401
+
402
+ add_settings_field(
403
+ 'wcap_fb_user_icon',
404
+ __( 'Icon size of user', 'woocommerce-abandoned-cart' ),
405
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_dropdown_callback' ),
406
+ 'woocommerce_ac_fb_page',
407
+ 'wcap_fb_settings_section',
408
+ array(
409
+
410
+ __( '<i>Select the size of user icon which shall be displayed below the checkbox in case the user is logged in.</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg,
411
+
412
+ 'wcap_fb_user_icon',
413
+
414
+ array(
415
+
416
+ 'small' => __( 'Small', 'woocommerce-abandoned-cart' ),
417
+
418
+ 'medium' => __( 'Medium', 'woocommerce-abandoned-cart' ),
419
+
420
+ 'large' => __( 'Large', 'woocommerce-abandoned-cart' ),
421
+
422
+ 'standard' => __( 'Standard', 'woocommerce-abandoned-cart' ),
423
+
424
+ 'xlarge' => __( 'Extra Large', 'woocommerce-abandoned-cart' ),
425
+
426
+ ),
427
+
428
+ )
429
+ );
430
+
431
+ add_settings_field(
432
+ 'wcap_fb_consent_text',
433
+ __( 'Consent text', 'woocommerce-abandoned-cart' ),
434
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
435
+ 'woocommerce_ac_fb_page',
436
+ 'wcap_fb_settings_section',
437
+ array( __( '<i>Text that will appear above the consent checkbox. HTML tags are also allowed.</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_consent_text' )
438
+ );
439
+
440
+ add_settings_field(
441
+ 'wcap_fb_page_id',
442
+ __( 'Facebook Page ID', 'woocommerce-abandoned-cart' ),
443
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
444
+ 'woocommerce_ac_fb_page',
445
+ 'wcap_fb_settings_section',
446
+ array( __( "<i>Facebook Page ID in numberic format. You can find your page ID from <a href='https://www.tychesoftwares.com/docs/docs/abandoned-cart-pro-for-woocommerce/send-abandoned-cart-reminder-notifications-using-facebook-messenger#fbpageid' target='_blank'>here</a></i>", 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_page_id' )
447
+ );
448
+
449
+ add_settings_field(
450
+ 'wcap_fb_app_id',
451
+ __( 'Messenger App ID', 'woocommerce-abandoned-cart' ),
452
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
453
+ 'woocommerce_ac_fb_page',
454
+ 'wcap_fb_settings_section',
455
+ array( __( '<i>Enter your Messenger App ID</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_app_id' )
456
+ );
457
+
458
+ add_settings_field(
459
+ 'wcap_fb_page_token',
460
+ __( 'Facebook Page Token', 'woocommerce-abandoned-cart' ),
461
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
462
+ 'woocommerce_ac_fb_page',
463
+ 'wcap_fb_settings_section',
464
+ array( __( '<i>Enter your Facebook Page Token</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_page_token' )
465
+ );
466
+
467
+ add_settings_field(
468
+ 'wcap_fb_verify_token',
469
+ __( 'Verify Token', 'woocommerce-abandoned-cart' ),
470
+ array( 'WCAP_Pro_Settings_Callbacks', 'wcap_fb_text_callback' ),
471
+ 'woocommerce_ac_fb_page',
472
+ 'wcap_fb_settings_section',
473
+ array( __( '<i>Enter your Verify Token</i>', 'woocommerce-abandoned-cart' ) . $upgrade_pro_msg, 'wcap_fb_verify_token' )
474
+ );
475
+
476
+ register_setting(
477
+ 'woocommerce_fb_settings',
478
+ 'wcap_enable_fb_reminders'
479
+ );
480
+
481
+ register_setting(
482
+ 'woocommerce_fb_settings',
483
+ 'wcap_enable_fb_reminders_popup'
484
+ );
485
+
486
+ register_setting(
487
+ 'woocommerce_fb_settings',
488
+ 'wcap_fb_consent_text'
489
+ );
490
+
491
+ register_setting(
492
+ 'woocommerce_fb_settings',
493
+ 'wcap_fb_page_id'
494
+ );
495
+
496
+ register_setting(
497
+ 'woocommerce_fb_settings',
498
+ 'wcap_fb_user_icon'
499
+ );
500
+
501
+ register_setting(
502
+ 'woocommerce_fb_settings',
503
+ 'wcap_fb_app_id'
504
+ );
505
+
506
+ register_setting(
507
+ 'woocommerce_fb_settings',
508
+ 'wcap_fb_page_token'
509
+ );
510
+
511
+ register_setting(
512
+ 'woocommerce_fb_settings',
513
+ 'wcap_fb_verify_token'
514
+ );
515
+
516
+ }
517
+
518
+ } // end of class
519
+
520
+ $WCAP_Pro_Settings = new WCAP_Pro_Settings();
521
 
522
  } // end if
523
 
524
+ ?>
includes/admin/wcap_pro_settings_callbacks.php CHANGED
@@ -3,587 +3,452 @@
3
  /**
4
 
5
  * Callbacks for all the settings present in the PRO version
6
-
7
- *
8
-
9
  * @since 2.4
10
-
11
  */
12
 
13
  // Exit if accessed directly
14
 
15
- if ( ! defined( 'ABSPATH' ) ) exit;
16
-
17
-
18
-
19
- if ( ! class_exists('WCAP_Pro_Settings_Callbacks' ) ) {
20
-
21
-
22
-
23
- class WCAP_Pro_Settings_Callbacks {
24
-
25
-
26
-
27
- /**
28
-
29
- * Construct
30
-
31
- * @since 4.9
32
-
33
- */
34
-
35
- public function __construct() {
36
-
37
- }
38
-
39
-
40
-
41
-
42
-
43
- public static function wcap_sms_settings_section_callback() {
44
-
45
- _e( 'Configure your Twilio account settings below. Please note that due to some restrictions from Twilio, customers <i>may sometimes</i> receive delayed messages', 'woocommerce-abandoned-cart' );
46
-
47
- }
48
-
49
-
50
-
51
- /**
52
-
53
- * Callback for enable SMS reminders
54
-
55
- * @param array $args Argument given while adding the field
56
-
57
- * @since 7.9
58
-
59
- */
60
-
61
- public static function wcap_enable_sms_reminders_callback( $args ) {
62
-
63
-
64
-
65
- $wcap_enable_sms = get_option( 'wcap_enable_sms_reminders' );
66
-
67
-
68
-
69
- if (isset( $wcap_enable_sms ) && $wcap_enable_sms == "" ) {
70
-
71
- $wcap_enable_sms = 'off';
72
-
73
- }
74
-
75
-
76
-
77
- $html = '<input type="checkbox" id="wcap_enable_sms_reminders" name="wcap_enable_sms_reminders" value="on" ' . checked( 'on', $wcap_enable_sms, false ) . ' readonly disabled/>';
78
-
79
-
80
-
81
- $html .= '<label for="wcap_enable_sms_reminders"> ' . $args[0] . '</label>';
82
-
83
- echo $html;
84
-
85
- }
86
-
87
-
88
-
89
- /**
90
-
91
- * Callback for From Phone Number
92
-
93
- * @param array $args Argument given while adding the field
94
-
95
- * @since 7.9
96
-
97
- */
98
-
99
- public static function wcap_sms_from_phone_callback( $args ) {
100
-
101
-
102
-
103
- $wcap_from_phone = get_option( 'wcap_sms_from_phone' );
104
-
105
-
106
-
107
- $html = "<input type='text' id='wcap_sms_from_phone' name='wcap_sms_from_phone' value='$wcap_from_phone' readonly />";
108
-
109
-
110
-
111
- $html .= '<label for="wcap_from_phone"> ' . $args[0] . '</label>';
112
-
113
- echo $html;
114
-
115
- }
116
-
117
-
118
-
119
- /**
120
-
121
- * Callback for Account SID
122
-
123
- * @param array $args Argument given while adding the field
124
-
125
- * @since 7.9
126
-
127
- */
128
-
129
- public static function wcap_sms_account_sid_callback( $args ) {
130
-
131
-
132
-
133
- $wcap_sms_account_sid = get_option( 'wcap_sms_account_sid' );
134
-
135
-
136
-
137
- $html = "<input type='text' style='width:60%;' id='wcap_sms_account_sid' name='wcap_sms_account_sid' value='$wcap_sms_account_sid' readonly />";
138
-
139
-
140
-
141
- $html .= '<label for="wcap_sms_account_sid"> ' . $args[0] . '</label>';
142
-
143
- echo $html;
144
-
145
- }
146
-
147
-
148
-
149
- /**
150
-
151
- * Callback for Auth Token
152
-
153
- * @param array $args Argument given while adding the field
154
-
155
- * @since 7.9
156
-
157
- */
158
-
159
- public static function wcap_sms_auth_token_callback( $args ) {
160
-
161
-
162
-
163
- $wcap_sms_auth_token = get_option( 'wcap_sms_auth_token' );
164
-
165
-
166
-
167
- $html = "<input type='text' style='width:60%;' id='wcap_sms_auth_token' name='wcap_sms_auth_token' value='$wcap_sms_auth_token' readonly />";
168
-
169
-
170
 
171
- $html .= '<label for="wcap_sms_auth_token"> ' . $args[0] . '</label>';
172
 
173
- echo $html;
174
 
175
-
176
 
177
- }
178
 
179
 
 
180
 
181
- static function wcap_fb_description(){
182
 
183
- _e( 'Configure the plugin to send notifications to Facebook Messenger using the settings below. Please refer the <a href="https://www.tychesoftwares.com/docs/docs/abandoned-cart-pro-for-woocommerce/send-abandoned-cart-reminder-notifications-using-facebook-messenger" target="_blank">following documentation</a> to complete the setup.', 'woocommerce-abandoned-cart' );
184
- }
185
 
 
186
 
 
187
 
188
- static function wcap_fb_checkbox_callback( $args ) {
 
189
 
 
190
 
 
191
 
192
- if( isset( $args[2]) ) {
193
- $checkbox_value = get_option( $args[2] );
194
- $args_2 = $args[2];
195
- } else {
196
- $checkbox_value = '';
197
- $args_2 = 'wcap_fb_check';
198
- }
199
 
200
-
201
 
202
- if (isset( $checkbox_value ) && $checkbox_value == "" ) {
203
 
204
- $checkbox_value = 'off';
205
 
206
- }
207
 
208
-
209
- $html = "<input type='checkbox' id='$args_2' name='$args_2' value='on' " . checked( 'on', $checkbox_value, false ) . " readonly disabled/>";
210
 
211
-
212
 
213
- $html .= '<label for="$args_2"> ' . $args[0] . '</label>';
214
 
215
 
 
216
 
217
- echo $html;
218
 
219
- }
220
 
 
 
221
 
 
222
 
223
- static function wcap_fb_text_callback( $args ) {
224
 
 
225
 
 
226
 
227
- $saved_value = isset( $args[2] ) ? get_option( $args[2] ) : '';
228
 
229
-
230
- if( isset( $args[2] ) ) {
231
- $html = "<input type='text' id='$args[2]' name='$args[2]' value='$saved_value' readonly />";
232
- } else {
233
- $html = "<input type='text' id='wcap_fb' name='wcap_fb' readonly />";
234
- }
235
 
236
-
237
 
238
- $html .= '<label for="$args[2]"> ' . $args[0] . '</label>';
239
 
240
- echo $html;
241
 
242
- }
243
 
244
 
 
245
 
246
- static function wcap_fb_dropdown_callback( $args ) {
247
 
 
248
 
 
 
249
 
250
- $selected_value = isset( $args[1] ) ? get_option( $args[1], '' ) : '';
251
 
252
- $selected = '';
253
 
 
254
 
255
- if( is_array( $args ) && isset( $args[1] ) && isset( $args[2] ) ) {
256
- $html = "<select name='$args[1]' id='$args[1]' disabled>";
257
- $icon_array = $args[2];
258
- } else {
259
- $html = "<select name='wcap_fb_user_icon' id='wcap_fb_user_icon' disabled>";
260
- $icon_array = array( 'small' => 'Small', 'medium' => 'Medium' );
261
- }
262
-
263
- foreach ( $icon_array as $key => $value ) {
264
 
265
- $selected = $selected_value === $key ? 'selected="selected"' : '';
266
 
267
- $html .= "<option value='$key' " . $selected . ">$value</option>";
268
 
269
- }
270
 
271
- $html .= "</select>";
272
 
273
- $html .= '<label for="$args[1]"> ' . $args[0] . '</label>';
274
 
275
- echo $html;
276
 
277
- }
278
 
279
- public static function wcap_cart_abandoned_time_guest_callback($args) {
 
280
 
281
-
282
 
283
- $cart_abandoned_time_guest = get_option( 'ac_cart_abandoned_time_guest' );
284
 
 
285
 
 
286
 
287
- printf(
288
 
289
- '<input type="text" id="ac_cart_abandoned_time_guest" name="ac_cart_abandoned_time_guest" value="%s" readonly />',
290
 
291
- isset( $cart_abandoned_time_guest ) ? esc_attr( $cart_abandoned_time_guest ) : ''
292
 
293
- );
294
 
 
295
 
 
296
 
297
- $html = '<label for="ac_cart_abandoned_time_guest"> ' . $args[0] . '</label>';
298
 
299
- echo $html;
 
300
 
301
- }
302
 
 
303
 
 
304
 
305
- public static function wcap_disable_guest_cart_email_callback( $args ) {
306
 
307
-
308
 
309
- $disable_guest_cart_email = get_option( 'ac_disable_guest_cart_email' );
310
 
311
-
312
 
313
- if ( isset( $disable_guest_cart_email ) && $disable_guest_cart_email == '' ) {
314
 
315
- $disable_guest_cart_email = 'off';
316
 
317
- }
 
318
 
319
-
320
 
321
- $html='';
322
 
323
- printf(
324
 
325
- '<input type="checkbox" id="ac_disable_guest_cart_email" name="ac_disable_guest_cart_email" value="on"
 
 
 
 
 
 
326
 
327
- '.checked( 'on', $disable_guest_cart_email, false ) . ' readonly disabled/>'
328
 
329
- );
330
 
331
-
332
 
333
- $html .= '<label for="ac_disable_guest_cart_email"> ' . $args[0] . '</label> <br> <div id ="wcap_atc_disable_msg" class="wcap_atc_disable_msg"></div>';
334
 
335
- echo $html;
336
 
337
- }
338
 
 
339
 
340
 
341
- public static function wcap_disable_logged_in_cart_email_callback( $args ) {
342
 
343
-
344
 
345
- $disable_logged_in_cart_email = get_option( 'ac_disable_logged_in_cart_email' );
346
 
347
-
 
 
 
 
348
 
349
- if ( isset( $disable_logged_in_cart_email ) && $disable_logged_in_cart_email == '' ) {
350
 
351
- $disable_logged_in_cart_email = 'off';
352
 
353
- }
354
 
355
-
356
 
357
- $html='';
358
 
359
- printf(
360
 
361
- '<input type="checkbox" id="ac_disable_logged_in_cart_email" name="ac_disable_logged_in_cart_email" value="on"
362
 
363
- '.checked( 'on', $disable_logged_in_cart_email, false ) . ' readonly disabled/>'
364
 
365
- );
 
 
 
 
 
 
 
 
 
366
 
367
-
368
 
369
- $html .= '<label for="ac_disable_logged_in_cart_email"> ' . $args[0] . '</label>';
370
 
371
- echo $html;
372
 
373
- }
374
 
 
375
 
 
376
 
377
- public static function wcap_capture_email_address_from_url( $args ) {
378
 
379
-
380
 
381
- $ac_capture_email_address_from_url = get_option( 'ac_capture_email_address_from_url' );
382
 
383
-
384
 
385
- printf(
 
 
 
386
 
387
- '<input type="text" id="ac_capture_email_address_from_url" name="ac_capture_email_address_from_url" value="%s" readonly />',
388
 
389
- isset( $ac_capture_email_address_from_url ) ? esc_attr( $ac_capture_email_address_from_url ) : ''
390
 
391
- );
392
 
393
-
394
 
395
- $html = '<label for="ac_capture_email_address_from_url_label"> ' . $args[0] . '</label>';
396
 
397
- echo $html;
398
 
399
- }
400
 
 
401
 
 
402
 
403
- public static function wcap_product_image_size_callback( $args ) {
404
 
405
-
406
 
407
- $wcap_product_image_height = get_option( 'wcap_product_image_height' );
 
408
 
409
- $wcap_product_image_width = get_option( 'wcap_product_image_width' );
 
410
 
411
-
412
 
413
- ?> <input type="text" id = "wcap_product_image_height" style= "width:50px" name="wcap_product_image_height" value="<?php echo $wcap_product_image_height; ?>" readonly />
414
 
415
- <?php echo "x"; ?>
416
 
417
- <input type="text" id = "wcap_product_image_width" style = "width:50px" name="wcap_product_image_width" value="<?php echo $wcap_product_image_width; ?>" readonly />
418
 
419
- px
420
 
421
- <?php
422
 
423
-
424
 
425
- $html = '<label for="wcap_product_image_size"> ' . $args[0] . '</label>';
426
 
427
- echo $html;
428
 
429
- }
430
 
431
-
432
 
433
- public static function wcap_cron_job_callback () {}
 
434
 
 
 
435
 
 
436
 
437
- public static function wcap_use_auto_cron_callback( $args ) {
438
 
 
439
 
440
 
441
- $enable_auto_cron = get_option( 'wcap_use_auto_cron' );
442
 
 
443
 
 
444
 
445
- if( isset( $enable_auto_cron ) && '' == $enable_auto_cron ) {
 
 
 
446
 
447
- $enable_auto_cron = 'off';
448
 
449
- }
450
 
451
-
452
 
453
- $html='';
454
 
455
- printf(
456
 
457
- '<input type="checkbox" id="wcap_use_auto_cron" name="wcap_use_auto_cron" value="on"
458
 
459
- '.checked( 'on', $enable_auto_cron, false ) . ' readonly disabled/>'
460
 
461
- );
462
 
 
463
 
 
464
 
465
- $html .= '<label for="wcap_use_auto_cron_label"> ' . $args[0] . '</label>';
466
 
467
- echo $html;
468
 
469
- }
470
 
 
471
 
 
472
 
473
- public static function wcap_cron_time_duration_callback( $args ) {
474
 
475
-
476
 
477
- $wcap_cron_time_duration = get_option( 'wcap_cron_time_duration' );
478
 
479
-
480
 
481
- printf(
482
 
483
- '<input type="text" id="wcap_cron_time_duration" name="wcap_cron_time_duration" value="%s" readonly/>',
484
 
485
- isset( $wcap_cron_time_duration ) ? esc_attr( $wcap_cron_time_duration ) : ''
486
 
487
- );
488
 
 
489
 
 
490
 
491
- $html = '<label for="wcap_cron_time_duration"> ' . $args[0] . '</label>';
492
 
493
- echo $html;
494
 
495
- }
 
496
 
 
 
497
 
 
498
 
499
- public static function wcap_custom_restrict_callback () {}
500
 
501
-
502
 
503
- public static function wcap_restrict_ip_address_callback( $args ) {
504
 
505
-
506
 
507
- $wcap_restrict_ip_address = get_option( 'wcap_restrict_ip_address' );
508
 
509
- $value = isset( $wcap_restrict_ip_address ) ? esc_attr( $wcap_restrict_ip_address ) : '';
510
 
511
-
 
 
 
512
 
513
- printf(
514
 
515
- '<textarea rows="4" cols="50" id="wcap_restrict_ip_address" name="wcap_restrict_ip_address" placeholder="Add an IP address" readonly />' . $value .'</textarea>'
516
 
517
- );
518
 
519
-
520
 
521
- $html = '<label for="wcap_restrict_ip_address_label"> ' . $args[0] . '</label>';
522
 
523
- echo $html;
524
 
525
- }
526
 
527
 
 
528
 
529
- public static function wcap_restrict_email_address_callback( $args ) {
530
 
531
-
532
 
533
- $wcap_restrict_email_address = get_option( 'wcap_restrict_email_address' );
 
 
534
 
535
- $email_value = isset( $wcap_restrict_email_address ) ? esc_attr( $wcap_restrict_email_address ) : '';
536
 
537
-
538
 
539
- printf(
540
 
541
- '<textarea rows="4" cols="50" id="wcap_restrict_email_address" name="wcap_restrict_email_address" placeholder="Add an email address" readonly />' . $email_value .'</textarea>'
542
 
543
- );
544
 
545
-
546
 
547
- $html = '<label for="wcap_restrict_email_address_label"> ' . $args[0] . '</label>';
548
 
549
- echo $html;
550
 
551
- }
 
 
552
 
 
553
 
 
554
 
555
- public static function wcap_restrict_domain_address_callback( $args ) {
556
 
557
-
558
 
559
- $wcap_restrict_domain_address = get_option( 'wcap_restrict_domain_address' );
560
 
561
- $domain_value = isset( $wcap_restrict_domain_address ) ? esc_attr( $wcap_restrict_domain_address ) : '';
562
 
563
-
564
 
565
- printf(
566
 
567
- '<textarea rows="4" cols="50" id="wcap_restrict_domain_address" name="wcap_restrict_domain_address" placeholder="Add an email domain name (Ex. hotmail.com)" readonly/>' . $domain_value .'</textarea>'
 
 
568
 
569
- );
570
 
571
-
572
 
573
- $html = '<label for="wcap_restrict_domain_address_label"> ' . $args[0] . '</label>';
574
 
575
- echo $html;
576
 
577
- }
578
 
579
-
580
 
581
-
582
 
583
- } // end of class
584
 
585
- $WCAP_Pro_Settings_Callbacks = new WCAP_Pro_Settings_Callbacks();
586
 
587
  } // end if
588
 
589
- ?>
3
  /**
4
 
5
  * Callbacks for all the settings present in the PRO version
6
+ *
 
 
7
  * @since 2.4
 
8
  */
9
 
10
  // Exit if accessed directly
11
 
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
14
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
 
16
 
 
17
 
18
+ if ( ! class_exists( 'WCAP_Pro_Settings_Callbacks' ) ) {
19
 
 
20
 
21
 
22
+ class WCAP_Pro_Settings_Callbacks {
23
 
 
24
 
 
 
25
 
26
+ /**
27
 
28
+ * Construct
29
 
30
+ * @since 4.9
31
+ */
32
 
33
+ public function __construct() {
34
 
35
+ }
36
 
 
 
 
 
 
 
 
37
 
 
38
 
 
39
 
 
40
 
41
+ public static function wcap_sms_settings_section_callback() {
42
 
43
+ _e( 'Configure your Twilio account settings below. Please note that due to some restrictions from Twilio, customers <i>may sometimes</i> receive delayed messages', 'woocommerce-abandoned-cart' );
 
44
 
45
+ }
46
 
 
47
 
48
 
49
+ /**
50
 
51
+ * Callback for enable SMS reminders
52
 
53
+ * @param array $args Argument given while adding the field
54
 
55
+ * @since 7.9
56
+ */
57
 
58
+ public static function wcap_enable_sms_reminders_callback( $args ) {
59
 
60
+ $wcap_enable_sms = get_option( 'wcap_enable_sms_reminders' );
61
 
62
+ if ( isset( $wcap_enable_sms ) && $wcap_enable_sms == '' ) {
63
 
64
+ $wcap_enable_sms = 'off';
65
 
66
+ }
67
 
68
+ $html = '<input type="checkbox" id="wcap_enable_sms_reminders" name="wcap_enable_sms_reminders" value="on" ' . checked( 'on', $wcap_enable_sms, false ) . ' readonly disabled/>';
 
 
 
 
 
69
 
70
+ $html .= '<label for="wcap_enable_sms_reminders"> ' . $args[0] . '</label>';
71
 
72
+ echo $html;
73
 
74
+ }
75
 
 
76
 
77
 
78
+ /**
79
 
80
+ * Callback for From Phone Number
81
 
82
+ * @param array $args Argument given while adding the field
83
 
84
+ * @since 7.9
85
+ */
86
 
87
+ public static function wcap_sms_from_phone_callback( $args ) {
88
 
89
+ $wcap_from_phone = get_option( 'wcap_sms_from_phone' );
90
 
91
+ $html = "<input type='text' id='wcap_sms_from_phone' name='wcap_sms_from_phone' value='$wcap_from_phone' readonly />";
92
 
93
+ $html .= '<label for="wcap_from_phone"> ' . $args[0] . '</label>';
 
 
 
 
 
 
 
 
94
 
95
+ echo $html;
96
 
97
+ }
98
 
 
99
 
 
100
 
101
+ /**
102
 
103
+ * Callback for Account SID
104
 
105
+ * @param array $args Argument given while adding the field
106
 
107
+ * @since 7.9
108
+ */
109
 
110
+ public static function wcap_sms_account_sid_callback( $args ) {
111
 
112
+ $wcap_sms_account_sid = get_option( 'wcap_sms_account_sid' );
113
 
114
+ $html = "<input type='text' style='width:60%;' id='wcap_sms_account_sid' name='wcap_sms_account_sid' value='$wcap_sms_account_sid' readonly />";
115
 
116
+ $html .= '<label for="wcap_sms_account_sid"> ' . $args[0] . '</label>';
117
 
118
+ echo $html;
119
 
120
+ }
121
 
 
122
 
 
123
 
124
+ /**
125
 
126
+ * Callback for Auth Token
127
 
128
+ * @param array $args Argument given while adding the field
129
 
130
+ * @since 7.9
131
+ */
132
 
133
+ public static function wcap_sms_auth_token_callback( $args ) {
134
 
135
+ $wcap_sms_auth_token = get_option( 'wcap_sms_auth_token' );
136
 
137
+ $html = "<input type='text' style='width:60%;' id='wcap_sms_auth_token' name='wcap_sms_auth_token' value='$wcap_sms_auth_token' readonly />";
138
 
139
+ $html .= '<label for="wcap_sms_auth_token"> ' . $args[0] . '</label>';
140
 
141
+ echo $html;
142
 
143
+ }
144
 
 
145
 
 
146
 
147
+ static function wcap_fb_description() {
148
 
149
+ _e( 'Configure the plugin to send notifications to Facebook Messenger using the settings below. Please refer the <a href="https://www.tychesoftwares.com/docs/docs/abandoned-cart-pro-for-woocommerce/send-abandoned-cart-reminder-notifications-using-facebook-messenger" target="_blank">following documentation</a> to complete the setup.', 'woocommerce-abandoned-cart' );
150
+ }
151
 
 
152
 
 
153
 
154
+ static function wcap_fb_checkbox_callback( $args ) {
155
 
156
+ if ( isset( $args[2] ) ) {
157
+ $checkbox_value = get_option( $args[2] );
158
+ $args_2 = $args[2];
159
+ } else {
160
+ $checkbox_value = '';
161
+ $args_2 = 'wcap_fb_check';
162
+ }
163
 
164
+ if ( isset( $checkbox_value ) && $checkbox_value == '' ) {
165
 
166
+ $checkbox_value = 'off';
167
 
168
+ }
169
 
170
+ $html = "<input type='checkbox' id='$args_2' name='$args_2' value='on' " . checked( 'on', $checkbox_value, false ) . ' readonly disabled/>';
171
 
172
+ $html .= '<label for="$args_2"> ' . $args[0] . '</label>';
173
 
174
+ echo $html;
175
 
176
+ }
177
 
178
 
 
179
 
180
+ static function wcap_fb_text_callback( $args ) {
181
 
182
+ $saved_value = isset( $args[2] ) ? get_option( $args[2] ) : '';
183
 
184
+ if ( isset( $args[2] ) ) {
185
+ $html = "<input type='text' id='$args[2]' name='$args[2]' value='$saved_value' readonly />";
186
+ } else {
187
+ $html = "<input type='text' id='wcap_fb' name='wcap_fb' readonly />";
188
+ }
189
 
190
+ $html .= '<label for="$args[2]"> ' . $args[0] . '</label>';
191
 
192
+ echo $html;
193
 
194
+ }
195
 
 
196
 
 
197
 
198
+ static function wcap_fb_dropdown_callback( $args ) {
199
 
200
+ $selected_value = isset( $args[1] ) ? get_option( $args[1], '' ) : '';
201
 
202
+ $selected = '';
203
 
204
+ if ( is_array( $args ) && isset( $args[1] ) && isset( $args[2] ) ) {
205
+ $html = "<select name='$args[1]' id='$args[1]' disabled>";
206
+ $icon_array = $args[2];
207
+ } else {
208
+ $html = "<select name='wcap_fb_user_icon' id='wcap_fb_user_icon' disabled>";
209
+ $icon_array = array(
210
+ 'small' => 'Small',
211
+ 'medium' => 'Medium',
212
+ );
213
+ }
214
 
215
+ foreach ( $icon_array as $key => $value ) {
216
 
217
+ $selected = $selected_value === $key ? 'selected="selected"' : '';
218
 
219
+ $html .= "<option value='$key' " . $selected . ">$value</option>";
220
 
221
+ }
222
 
223
+ $html .= '</select>';
224
 
225
+ $html .= '<label for="$args[1]"> ' . $args[0] . '</label>';
226
 
227
+ echo $html;
228
 
229
+ }
230
 
231
+ public static function wcap_cart_abandoned_time_guest_callback( $args ) {
232
 
233
+ $cart_abandoned_time_guest = get_option( 'ac_cart_abandoned_time_guest' );
234
 
235
+ printf(
236
+ '<input type="text" id="ac_cart_abandoned_time_guest" name="ac_cart_abandoned_time_guest" value="%s" readonly />',
237
+ isset( $cart_abandoned_time_guest ) ? esc_attr( $cart_abandoned_time_guest ) : ''
238
+ );
239
 
240
+ $html = '<label for="ac_cart_abandoned_time_guest"> ' . $args[0] . '</label>';
241
 
242
+ echo $html;
243
 
244
+ }
245
 
 
246
 
 
247
 
248
+ public static function wcap_disable_guest_cart_email_callback( $args ) {
249
 
250
+ $disable_guest_cart_email = get_option( 'ac_disable_guest_cart_email' );
251
 
252
+ if ( isset( $disable_guest_cart_email ) && $disable_guest_cart_email == '' ) {
253
 
254
+ $disable_guest_cart_email = 'off';
255
 
256
+ }
257
 
258
+ $html = '';
259
 
260
+ printf(
261
+ '<input type="checkbox" id="ac_disable_guest_cart_email" name="ac_disable_guest_cart_email" value="on"
262
 
263
+ ' . checked( 'on', $disable_guest_cart_email, false ) . ' readonly disabled/>'
264
+ );
265
 
266
+ $html .= '<label for="ac_disable_guest_cart_email"> ' . $args[0] . '</label> <br> <div id ="wcap_atc_disable_msg" class="wcap_atc_disable_msg"></div>';
267
 
268
+ echo $html;
269
 
270
+ }
271
 
 
272
 
 
273
 
274
+ public static function wcap_disable_logged_in_cart_email_callback( $args ) {
275
 
276
+ $disable_logged_in_cart_email = get_option( 'ac_disable_logged_in_cart_email' );
277
 
278
+ if ( isset( $disable_logged_in_cart_email ) && $disable_logged_in_cart_email == '' ) {
279
 
280
+ $disable_logged_in_cart_email = 'off';
281
 
282
+ }
283
 
284
+ $html = '';
285
 
286
+ printf(
287
+ '<input type="checkbox" id="ac_disable_logged_in_cart_email" name="ac_disable_logged_in_cart_email" value="on"
288
 
289
+ ' . checked( 'on', $disable_logged_in_cart_email, false ) . ' readonly disabled/>'
290
+ );
291
 
292
+ $html .= '<label for="ac_disable_logged_in_cart_email"> ' . $args[0] . '</label>';
293
 
294
+ echo $html;
295
 
296
+ }
297
 
298
 
 
299
 
300
+ public static function wcap_capture_email_address_from_url( $args ) {
301
 
302
+ $ac_capture_email_address_from_url = get_option( 'ac_capture_email_address_from_url' );
303
 
304
+ printf(
305
+ '<input type="text" id="ac_capture_email_address_from_url" name="ac_capture_email_address_from_url" value="%s" readonly />',
306
+ isset( $ac_capture_email_address_from_url ) ? esc_attr( $ac_capture_email_address_from_url ) : ''
307
+ );
308
 
309
+ $html = '<label for="ac_capture_email_address_from_url_label"> ' . $args[0] . '</label>';
310
 
311
+ echo $html;
312
 
313
+ }
314
 
 
315
 
 
316
 
317
+ public static function wcap_product_image_size_callback( $args ) {
318
 
319
+ $wcap_product_image_height = get_option( 'wcap_product_image_height' );
320
 
321
+ $wcap_product_image_width = get_option( 'wcap_product_image_width' );
322
 
323
+ ?> <input type="text" id = "wcap_product_image_height" style= "width:50px" name="wcap_product_image_height" value="<?php echo $wcap_product_image_height; ?>" readonly />
324
 
325
+ <?php echo 'x'; ?>
326
 
327
+ <input type="text" id = "wcap_product_image_width" style = "width:50px" name="wcap_product_image_width" value="<?php echo $wcap_product_image_width; ?>" readonly />
328
 
329
+ px
330
 
331
+ <?php
332
 
333
+ $html = '<label for="wcap_product_image_size"> ' . $args[0] . '</label>';
334
 
335
+ echo $html;
336
 
337
+ }
338
 
 
339
 
 
340
 
341
+ public static function wcap_cron_job_callback() {}
342
 
 
343
 
 
344
 
345
+ public static function wcap_use_auto_cron_callback( $args ) {
346
 
347
+ $enable_auto_cron = get_option( 'wcap_use_auto_cron' );
348
 
349
+ if ( isset( $enable_auto_cron ) && '' == $enable_auto_cron ) {
350
 
351
+ $enable_auto_cron = 'off';
352
 
353
+ }
354
 
355
+ $html = '';
356
 
357
+ printf(
358
+ '<input type="checkbox" id="wcap_use_auto_cron" name="wcap_use_auto_cron" value="on"
359
 
360
+ ' . checked( 'on', $enable_auto_cron, false ) . ' readonly disabled/>'
361
+ );
362
 
363
+ $html .= '<label for="wcap_use_auto_cron_label"> ' . $args[0] . '</label>';
364
 
365
+ echo $html;
366
 
367
+ }
368
 
 
369
 
 
370
 
371
+ public static function wcap_cron_time_duration_callback( $args ) {
372
 
373
+ $wcap_cron_time_duration = get_option( 'wcap_cron_time_duration' );
374
 
375
+ printf(
376
+ '<input type="text" id="wcap_cron_time_duration" name="wcap_cron_time_duration" value="%s" readonly/>',
377
+ isset( $wcap_cron_time_duration ) ? esc_attr( $wcap_cron_time_duration ) : ''
378
+ );
379
 
380
+ $html = '<label for="wcap_cron_time_duration"> ' . $args[0] . '</label>';
381
 
382
+ echo $html;
383
 
384
+ }
385
 
 
386
 
 
387
 
388
+ public static function wcap_custom_restrict_callback() {}
389
 
 
390
 
391
 
392
+ public static function wcap_restrict_ip_address_callback( $args ) {
393
 
394
+ $wcap_restrict_ip_address = get_option( 'wcap_restrict_ip_address' );
395
 
396
+ $value = isset( $wcap_restrict_ip_address ) ? esc_attr( $wcap_restrict_ip_address ) : '';
397
 
398
+ printf(
399
+ '<textarea rows="4" cols="50" id="wcap_restrict_ip_address" name="wcap_restrict_ip_address" placeholder="Add an IP address" readonly />' . $value . '</textarea>'
400
+ );
401
 
402
+ $html = '<label for="wcap_restrict_ip_address_label"> ' . $args[0] . '</label>';
403
 
404
+ echo $html;
405
 
406
+ }
407
 
 
408
 
 
409
 
410
+ public static function wcap_restrict_email_address_callback( $args ) {
411
 
412
+ $wcap_restrict_email_address = get_option( 'wcap_restrict_email_address' );
413
 
414
+ $email_value = isset( $wcap_restrict_email_address ) ? esc_attr( $wcap_restrict_email_address ) : '';
415
 
416
+ printf(
417
+ '<textarea rows="4" cols="50" id="wcap_restrict_email_address" name="wcap_restrict_email_address" placeholder="Add an email address" readonly />' . $email_value . '</textarea>'
418
+ );
419
 
420
+ $html = '<label for="wcap_restrict_email_address_label"> ' . $args[0] . '</label>';
421
 
422
+ echo $html;
423
 
424
+ }
425
 
 
426
 
 
427
 
428
+ public static function wcap_restrict_domain_address_callback( $args ) {
429
 
430
+ $wcap_restrict_domain_address = get_option( 'wcap_restrict_domain_address' );
431
 
432
+ $domain_value = isset( $wcap_restrict_domain_address ) ? esc_attr( $wcap_restrict_domain_address ) : '';
433
 
434
+ printf(
435
+ '<textarea rows="4" cols="50" id="wcap_restrict_domain_address" name="wcap_restrict_domain_address" placeholder="Add an email domain name (Ex. hotmail.com)" readonly/>' . $domain_value . '</textarea>'
436
+ );
437
 
438
+ $html = '<label for="wcap_restrict_domain_address_label"> ' . $args[0] . '</label>';
439
 
440
+ echo $html;
441
 
442
+ }
443
 
 
444
 
 
445
 
 
446
 
 
447
 
448
+ } // end of class
449
 
450
+ $WCAP_Pro_Settings_Callbacks = new WCAP_Pro_Settings_Callbacks();
451
 
452
  } // end if
453
 
454
+ ?>
includes/class-wcal-admin-notice.php CHANGED
@@ -31,16 +31,15 @@ class Wcal_Admin_Notice {
31
 
32
  if ( isset( $_GET['page'] ) && 'woocommerce_ac_page' === $_GET['page'] ) {
33
 
34
- if ( ! get_option( 'wcal_scheduler_update_dismiss', FALSE ) ) {
35
  $post_link = '<a href="https://www.tychesoftwares.com/moving-to-the-action-scheduler-library/?utm_source=AcLiteNotice&utm_medium=link&utm_campaign=AbandonCartLite" target="_blank">here</a>';
36
  ?>
37
  <div id='wcal_cron_notice' class='is-dismissible notice notice-info wcal-cron-notice'>
38
  <p><?php _e( "The <b>Abandoned Cart Lite for WooCommerce</b> now uses the Action Scheduler library to send reminders. For further details, please visit $post_link.", 'woocommerce-abandoned-cart' ); ?></p>
39
  </div>
40
- <?php
41
  }
42
  }
43
-
44
 
45
  if ( isset( $_GET['ac_update'] ) && 'email_templates' === $_GET['ac_update'] ) {
46
  return;
31
 
32
  if ( isset( $_GET['page'] ) && 'woocommerce_ac_page' === $_GET['page'] ) {
33
 
34
+ if ( ! get_option( 'wcal_scheduler_update_dismiss', false ) ) {
35
  $post_link = '<a href="https://www.tychesoftwares.com/moving-to-the-action-scheduler-library/?utm_source=AcLiteNotice&utm_medium=link&utm_campaign=AbandonCartLite" target="_blank">here</a>';
36
  ?>
37
  <div id='wcal_cron_notice' class='is-dismissible notice notice-info wcal-cron-notice'>
38
  <p><?php _e( "The <b>Abandoned Cart Lite for WooCommerce</b> now uses the Action Scheduler library to send reminders. For further details, please visit $post_link.", 'woocommerce-abandoned-cart' ); ?></p>
39
  </div>
40
+ <?php
41
  }
42
  }
 
43
 
44
  if ( isset( $_GET['ac_update'] ) && 'email_templates' === $_GET['ac_update'] ) {
45
  return;
includes/classes/class-wcal-aes-counter.php CHANGED
@@ -1,9 +1,14 @@
1
  <?php
2
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3
- /* AES counter (CTR) mode implementation in PHP */
4
- /* (c) Chris Veness 2005-2014 www.movable-type.co.uk/scripts */
5
- /* Right of free use is granted for all commercial or non-commercial use under CC-BY licence. */
6
- /* No warranty of any form is offered. */
 
 
 
 
 
7
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
8
  /**
9
  * Abandoned Cart Lite for WooCommerce
@@ -16,170 +21,208 @@
16
 
17
  /**
18
  * This class will encrypt and decrypt the data.
 
19
  * @since 2.8
20
  */
21
- Class Wcal_Aes_Ctr extends Wcal_Aes
22
- {
23
-
24
- /**
25
- * Encrypt a text using AES encryption in Counter mode of operation
26
- * - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
27
- *
28
- * Unicode multi-byte character safe
29
- *
30
- * @param plaintext source text to be encrypted
31
- * @param password the password to use to generate a key
32
- * @param nBits number of bits to be used in the key (128, 192, or 256)
33
- * @return encrypted text
34
- * @since 2.8
35
- */
36
- public static function encrypt($plaintext, $password, $nBits)
37
- {
38
- $blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
39
- if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) return ''; // standard allows 128/192/256 bit keys
40
- // note PHP (5) gives us plaintext and password in UTF8 encoding!
41
-
42
- // use AES itself to encrypt password to get cipher key (using plain password as source for
43
- // key expansion) - gives us well encrypted key
44
- $nBytes = $nBits / 8; // no bytes in key
45
- $pwBytes = array();
46
- for ($i = 0; $i < $nBytes; $i++) $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
47
- $key = Wcal_Aes::cipher($pwBytes, Wcal_Aes::keyExpansion($pwBytes));
48
- $key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
49
-
50
- // initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A �B.2): [0-1] = millisec,
51
- // [2-3] = random, [4-7] = seconds, giving guaranteed sub-ms uniqueness up to Feb 2106
52
- $counterBlock = array();
53
- $nonce = floor(microtime(true) * 1000); // timestamp: milliseconds since 1-Jan-1970
54
- $nonceMs = $nonce % 1000;
55
- $nonceSec = floor($nonce / 1000);
56
- $nonceRnd = floor(rand(0, 0xffff));
57
-
58
- for ($i = 0; $i < 2; $i++) $counterBlock[$i] = self::urs($nonceMs, $i * 8) & 0xff;
59
- for ($i = 0; $i < 2; $i++) $counterBlock[$i + 2] = self::urs($nonceRnd, $i * 8) & 0xff;
60
- for ($i = 0; $i < 4; $i++) $counterBlock[$i + 4] = self::urs($nonceSec, $i * 8) & 0xff;
61
-
62
- // and convert it to a string to go on the front of the ciphertext
63
- $ctrTxt = '';
64
- for ($i = 0; $i < 8; $i++) $ctrTxt .= chr($counterBlock[$i]);
65
-
66
- // generate key schedule - an expansion of the key into distinct Key Rounds for each round
67
- $keySchedule = Wcal_Aes::keyExpansion($key);
68
- //print_r($keySchedule);
69
-
70
- $blockCount = ceil(strlen($plaintext) / $blockSize);
71
- $ciphertxt = array(); // ciphertext as array of strings
72
-
73
- for ($b = 0; $b < $blockCount; $b++) {
74
- // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
75
- // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
76
- for ($c = 0; $c < 4; $c++) $counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
77
- for ($c = 0; $c < 4; $c++) $counterBlock[15 - $c - 4] = self::urs($b / 0x100000000, $c * 8);
78
-
79
- $cipherCntr = Wcal_Aes::cipher($counterBlock, $keySchedule); // -- encrypt counter block --
80
-
81
- // block size is reduced on final block
82
- $blockLength = $b < $blockCount - 1 ? $blockSize : (strlen($plaintext) - 1) % $blockSize + 1;
83
- $cipherByte = array();
84
-
85
- for ($i = 0; $i < $blockLength; $i++) { // -- xor plaintext with ciphered counter byte-by-byte --
86
- $cipherByte[$i] = $cipherCntr[$i] ^ ord(substr($plaintext, $b * $blockSize + $i, 1));
87
- $cipherByte[$i] = chr($cipherByte[$i]);
88
- }
89
- $ciphertxt[$b] = implode('', $cipherByte); // escape troublesome characters in ciphertext
90
- }
91
-
92
- // implode is more efficient than repeated string concatenation
93
- $ciphertext = $ctrTxt . implode('', $ciphertxt);
94
- $ciphertext = base64_encode($ciphertext);
95
- return $ciphertext;
96
- }
97
-
98
-
99
- /**
100
- * Decrypt a text encrypted by AES in counter mode of operation
101
- *
102
- * @param ciphertext source text to be decrypted
103
- * @param password the password to use to generate a key
104
- * @param nBits number of bits to be used in the key (128, 192, or 256)
105
- * @return decrypted text
106
- * @since 2.8
107
- */
108
- public static function decrypt($ciphertext, $password, $nBits)
109
- {
110
- $blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
111
- if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) return ''; // standard allows 128/192/256 bit keys
112
- $ciphertext = base64_decode($ciphertext);
113
-
114
- // use AES to encrypt password (mirroring encrypt routine)
115
- $nBytes = $nBits / 8; // no bytes in key
116
- $pwBytes = array();
117
- for ($i = 0; $i < $nBytes; $i++) $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
118
- $key = Wcal_Aes::cipher($pwBytes, Wcal_Aes::keyExpansion($pwBytes));
119
- $key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
120
-
121
- // recover nonce from 1st element of ciphertext
122
- $counterBlock = array();
123
- $ctrTxt = substr($ciphertext, 0, 8);
124
- for ($i = 0; $i < 8; $i++) $counterBlock[$i] = ord(substr($ctrTxt, $i, 1));
125
-
126
- // generate key schedule
127
- $keySchedule = Wcal_Aes::keyExpansion($key);
128
-
129
- // separate ciphertext into blocks (skipping past initial 8 bytes)
130
- $nBlocks = ceil((strlen($ciphertext) - 8) / $blockSize);
131
- $ct = array();
132
- for ($b = 0; $b < $nBlocks; $b++) $ct[$b] = substr($ciphertext, 8 + $b * $blockSize, 16);
133
- $ciphertext = $ct; // ciphertext is now array of block-length strings
134
-
135
- // plaintext will get generated block-by-block into array of block-length strings
136
- $plaintxt = array();
137
-
138
- for ($b = 0; $b < $nBlocks; $b++) {
139
- // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
140
- for ($c = 0; $c < 4; $c++) $counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
141
- for ($c = 0; $c < 4; $c++) $counterBlock[15 - $c - 4] = self::urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff;
142
-
143
- $cipherCntr = Wcal_Aes::cipher($counterBlock, $keySchedule); // encrypt counter block
144
-
145
- $plaintxtByte = array();
146
- for ($i = 0; $i < strlen($ciphertext[$b]); $i++) {
147
- // -- xor plaintext with ciphered counter byte-by-byte --
148
- $plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1));
149
- $plaintxtByte[$i] = chr($plaintxtByte[$i]);
150
-
151
- }
152
- $plaintxt[$b] = implode('', $plaintxtByte);
153
- }
154
-
155
- // join array of blocks into single plaintext string
156
- $plaintext = implode('', $plaintxt);
157
-
158
- return $plaintext;
159
- }
160
-
161
-
162
- /**
163
- * Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
164
- *
165
- * @param a number to be shifted (32-bit integer)
166
- * @param b number of bits to shift a to the right (0..31)
167
- * @return a right-shifted and zero-filled by b bits
168
- * @since 2.8
169
- */
170
- private static function urs($a, $b)
171
- {
172
- $a &= 0xffffffff;
173
- $b &= 0x1f; // (bounds check)
174
- if ($a & 0x80000000 && $b > 0) { // if left-most bit set
175
- $a = ($a >> 1) & 0x7fffffff; // right-shift one bit & clear left-most bit
176
- $check = $b - 1 ;
177
- $a = $a >> ($check); // remaining right-shifts
178
- } else { // otherwise
179
- $a = ($a >> $b); // use normal right-shift
180
- }
181
- return $a;
182
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  }
185
 
1
  <?php
2
+ /*
3
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4
+ /*
5
+ AES counter (CTR) mode implementation in PHP */
6
+ /*
7
+ (c) Chris Veness 2005-2014 www.movable-type.co.uk/scripts */
8
+ /*
9
+ Right of free use is granted for all commercial or non-commercial use under CC-BY licence. */
10
+ /*
11
+ No warranty of any form is offered. */
12
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
13
  /**
14
  * Abandoned Cart Lite for WooCommerce
21
 
22
  /**
23
  * This class will encrypt and decrypt the data.
24
+ *
25
  * @since 2.8
26
  */
27
+ class Wcal_Aes_Ctr extends Wcal_Aes {
28
+
29
+
30
+ /**
31
+ * Encrypt a text using AES encryption in Counter mode of operation
32
+ * - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
33
+ *
34
+ * Unicode multi-byte character safe
35
+ *
36
+ * @param plaintext source text to be encrypted
37
+ * @param password the password to use to generate a key
38
+ * @param nBits number of bits to be used in the key (128, 192, or 256)
39
+ * @return encrypted text
40
+ * @since 2.8
41
+ */
42
+ public static function encrypt( $plaintext, $password, $nBits ) {
43
+ $blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
44
+ if ( ! ( $nBits == 128 || $nBits == 192 || $nBits == 256 ) ) {
45
+ return ''; // standard allows 128/192/256 bit keys
46
+ }
47
+ // note PHP (5) gives us plaintext and password in UTF8 encoding!
48
+
49
+ // use AES itself to encrypt password to get cipher key (using plain password as source for
50
+ // key expansion) - gives us well encrypted key
51
+ $nBytes = $nBits / 8; // no bytes in key
52
+ $pwBytes = array();
53
+ for ( $i = 0; $i < $nBytes;
54
+ $i++ ) {
55
+ $pwBytes[ $i ] = ord( substr( $password, $i, 1 ) ) & 0xff;
56
+ }
57
+ $key = Wcal_Aes::cipher( $pwBytes, Wcal_Aes::keyExpansion( $pwBytes ) );
58
+ $key = array_merge( $key, array_slice( $key, 0, $nBytes - 16 ) ); // expand key to 16/24/32 bytes long
59
+
60
+ // initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A �B.2): [0-1] = millisec,
61
+ // [2-3] = random, [4-7] = seconds, giving guaranteed sub-ms uniqueness up to Feb 2106
62
+ $counterBlock = array();
63
+ $nonce = floor( microtime( true ) * 1000 ); // timestamp: milliseconds since 1-Jan-1970
64
+ $nonceMs = $nonce % 1000;
65
+ $nonceSec = floor( $nonce / 1000 );
66
+ $nonceRnd = floor( rand( 0, 0xffff ) );
67
+
68
+ for ( $i = 0; $i < 2;
69
+ $i++ ) {
70
+ $counterBlock[ $i ] = self::urs( $nonceMs, $i * 8 ) & 0xff;
71
+ }
72
+ for ( $i = 0; $i < 2;
73
+ $i++ ) {
74
+ $counterBlock[ $i + 2 ] = self::urs( $nonceRnd, $i * 8 ) & 0xff;
75
+ }
76
+ for ( $i = 0; $i < 4;
77
+ $i++ ) {
78
+ $counterBlock[ $i + 4 ] = self::urs( $nonceSec, $i * 8 ) & 0xff;
79
+ }
80
+
81
+ // and convert it to a string to go on the front of the ciphertext
82
+ $ctrTxt = '';
83
+ for ( $i = 0; $i < 8;
84
+ $i++ ) {
85
+ $ctrTxt .= chr( $counterBlock[ $i ] );
86
+ }
87
+
88
+ // generate key schedule - an expansion of the key into distinct Key Rounds for each round
89
+ $keySchedule = Wcal_Aes::keyExpansion( $key );
90
+ // print_r($keySchedule);
91
+
92
+ $blockCount = ceil( strlen( $plaintext ) / $blockSize );
93
+ $ciphertxt = array(); // ciphertext as array of strings
94
+
95
+ for ( $b = 0; $b < $blockCount; $b++ ) {
96
+ // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
97
+ // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
98
+ for ( $c = 0; $c < 4;
99
+ $c++ ) {
100
+ $counterBlock[ 15 - $c ] = self::urs( $b, $c * 8 ) & 0xff;
101
+ }
102
+ for ( $c = 0; $c < 4;
103
+ $c++ ) {
104
+ $counterBlock[ 15 - $c - 4 ] = self::urs( $b / 0x100000000, $c * 8 );
105
+ }
106
+
107
+ $cipherCntr = Wcal_Aes::cipher( $counterBlock, $keySchedule ); // -- encrypt counter block --
108
+
109
+ // block size is reduced on final block
110
+ $blockLength = $b < $blockCount - 1 ? $blockSize : ( strlen( $plaintext ) - 1 ) % $blockSize + 1;
111
+ $cipherByte = array();
112
+
113
+ for ( $i = 0; $i < $blockLength; $i++ ) { // -- xor plaintext with ciphered counter byte-by-byte --
114
+ $cipherByte[ $i ] = $cipherCntr[ $i ] ^ ord( substr( $plaintext, $b * $blockSize + $i, 1 ) );
115
+ $cipherByte[ $i ] = chr( $cipherByte[ $i ] );
116
+ }
117
+ $ciphertxt[ $b ] = implode( '', $cipherByte ); // escape troublesome characters in ciphertext
118
+ }
119
+
120
+ // implode is more efficient than repeated string concatenation
121
+ $ciphertext = $ctrTxt . implode( '', $ciphertxt );
122
+ $ciphertext = base64_encode( $ciphertext );
123
+ return $ciphertext;
124
+ }
125
+
126
+
127
+ /**
128
+ * Decrypt a text encrypted by AES in counter mode of operation
129
+ *
130
+ * @param ciphertext source text to be decrypted
131
+ * @param password the password to use to generate a key
132
+ * @param nBits number of bits to be used in the key (128, 192, or 256)
133
+ * @return decrypted text
134
+ * @since 2.8
135
+ */
136
+ public static function decrypt( $ciphertext, $password, $nBits ) {
137
+ $blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
138
+ if ( ! ( $nBits == 128 || $nBits == 192 || $nBits == 256 ) ) {
139
+ return ''; // standard allows 128/192/256 bit keys
140
+ }
141
+ $ciphertext = base64_decode( $ciphertext );
142
+
143
+ // use AES to encrypt password (mirroring encrypt routine)
144
+ $nBytes = $nBits / 8; // no bytes in key
145
+ $pwBytes = array();
146
+ for ( $i = 0; $i < $nBytes;
147
+ $i++ ) {
148
+ $pwBytes[ $i ] = ord( substr( $password, $i, 1 ) ) & 0xff;
149
+ }
150
+ $key = Wcal_Aes::cipher( $pwBytes, Wcal_Aes::keyExpansion( $pwBytes ) );
151
+ $key = array_merge( $key, array_slice( $key, 0, $nBytes - 16 ) ); // expand key to 16/24/32 bytes long
152
+
153
+ // recover nonce from 1st element of ciphertext
154
+ $counterBlock = array();
155
+ $ctrTxt = substr( $ciphertext, 0, 8 );
156
+ for ( $i = 0; $i < 8;
157
+ $i++ ) {
158
+ $counterBlock[ $i ] = ord( substr( $ctrTxt, $i, 1 ) );
159
+ }
160
+
161
+ // generate key schedule
162
+ $keySchedule = Wcal_Aes::keyExpansion( $key );
163
+
164
+ // separate ciphertext into blocks (skipping past initial 8 bytes)
165
+ $nBlocks = ceil( ( strlen( $ciphertext ) - 8 ) / $blockSize );
166
+ $ct = array();
167
+ for ( $b = 0; $b < $nBlocks;
168
+ $b++ ) {
169
+ $ct[ $b ] = substr( $ciphertext, 8 + $b * $blockSize, 16 );
170
+ }
171
+ $ciphertext = $ct; // ciphertext is now array of block-length strings
172
+
173
+ // plaintext will get generated block-by-block into array of block-length strings
174
+ $plaintxt = array();
175
+
176
+ for ( $b = 0; $b < $nBlocks; $b++ ) {
177
+ // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
178
+ for ( $c = 0; $c < 4;
179
+ $c++ ) {
180
+ $counterBlock[ 15 - $c ] = self::urs( $b, $c * 8 ) & 0xff;
181
+ }
182
+ for ( $c = 0; $c < 4;
183
+ $c++ ) {
184
+ $counterBlock[ 15 - $c - 4 ] = self::urs( ( $b + 1 ) / 0x100000000 - 1, $c * 8 ) & 0xff;
185
+ }
186
+
187
+ $cipherCntr = Wcal_Aes::cipher( $counterBlock, $keySchedule ); // encrypt counter block
188
+
189
+ $plaintxtByte = array();
190
+ for ( $i = 0; $i < strlen( $ciphertext[ $b ] ); $i++ ) {
191
+ // -- xor plaintext with ciphered counter byte-by-byte --
192
+ $plaintxtByte[ $i ] = $cipherCntr[ $i ] ^ ord( substr( $ciphertext[ $b ], $i, 1 ) );
193
+ $plaintxtByte[ $i ] = chr( $plaintxtByte[ $i ] );
194
+
195
+ }
196
+ $plaintxt[ $b ] = implode( '', $plaintxtByte );
197
+ }
198
+
199
+ // join array of blocks into single plaintext string
200
+ $plaintext = implode( '', $plaintxt );
201
+
202
+ return $plaintext;
203
+ }
204
+
205
+
206
+ /**
207
+ * Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
208
+ *
209
+ * @param a number to be shifted (32-bit integer)
210
+ * @param b number of bits to shift a to the right (0..31)
211
+ * @return a right-shifted and zero-filled by b bits
212
+ * @since 2.8
213
+ */
214
+ private static function urs( $a, $b ) {
215
+ $a &= 0xffffffff;
216
+ $b &= 0x1f; // (bounds check)
217
+ if ( $a & 0x80000000 && $b > 0 ) { // if left-most bit set
218
+ $a = ( $a >> 1 ) & 0x7fffffff; // right-shift one bit & clear left-most bit
219
+ $check = $b - 1;
220
+ $a = $a >> ( $check ); // remaining right-shifts
221
+ } else { // otherwise
222
+ $a = ( $a >> $b ); // use normal right-shift
223
+ }
224
+ return $a;
225
+ }
226
 
227
  }
228
 
includes/classes/class-wcal-aes.php CHANGED
@@ -1,9 +1,14 @@
1
  <?php
2
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3
- /* AES implementation in PHP */
4
- /* (c) Chris Veness 2005-2014 www.movable-type.co.uk/scripts */
5
- /* Right of free use is granted for all commercial or non-commercial use under CC-BY licence. */
6
- /* No warranty of any form is offered. */
 
 
 
 
 
7
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
8
 
9
  /**
@@ -17,195 +22,469 @@
17
 
18
  /**
19
  * It will genrate the encryption and decryption for data.
 
20
  * @since 2.8
21
  */
22
- Class Wcal_Aes
23
- {
24
- /**
25
- * AES Cipher function [�5.1]: encrypt 'input' with Rijndael algorithm
26
- *
27
- * @param input message as byte-array (16 bytes)
28
- * @param w key schedule as 2D byte-array (Nr+1 x Nb bytes) -
29
- * generated from the cipher key by keyExpansion()
30
- * @return ciphertext as byte-array (16 bytes)
31
- * @since 2.8
32
- */
33
- public static function cipher($input, $w)
34
- {
35
- $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
36
- $Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
37
- $state = array(); // initialise 4xNb byte-array 'state' with input [�3.4]
38
- for( $i = 0; $i < 4 * $Nb; $i++ ) $state[$i % 4][floor($i / 4)] = $input[$i];
39
-
40
- $state = self::addRoundKey( $state, $w, 0, $Nb );
41
-
42
- for ( $round = 1; $round < $Nr; $round++ ) { // apply Nr rounds
43
- $state = self::subBytes( $state, $Nb );
44
- $state = self::shiftRows( $state, $Nb );
45
- $state = self::mixColumns( $state, $Nb );
46
- $state = self::addRoundKey( $state, $w, $round, $Nb );
47
- }
48
-
49
- $state = self::subBytes( $state, $Nb );
50
- $state = self::shiftRows( $state, $Nb );
51
- $state = self::addRoundKey( $state, $w, $Nr, $Nb );
52
-
53
- $output = array( 4 * $Nb ); // convert state to 1-d array before returning [�3.4]
54
- for( $i = 0; $i < 4 * $Nb; $i++ ) $output[$i] = $state[$i % 4][floor($i / 4)];
55
- return $output;
56
- }
57
- /**
58
- * Xor Round Key into state S [�5.1.4].
59
- * @since 2.8
60
- */
61
- private static function addRoundKey( $state, $w, $rnd, $Nb )
62
- {
63
- for( $r = 0; $r < 4; $r++ ) {
64
- for ($c = 0; $c < $Nb; $c++) $state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
65
- }
66
- return $state;
67
- }
68
-
69
- /**
70
- * Apply SBox to state S [�5.1.1].
71
- * @since 2.8
72
- */
73
- private static function subBytes($s, $Nb)
74
- {
75
- for( $r = 0; $r < 4; $r++ ) {
76
- for( $c = 0; $c < $Nb; $c++ ) $s[$r][$c] = self::$sBox[$s[$r][$c]];
77
- }
78
- return $s;
79
- }
80
-
81
- /**
82
- * Shift row r of state S left by r bytes [�5.1.2].
83
- * @since 2.8
84
- */
85
- private static function shiftRows($s, $Nb)
86
- {
87
- $t = array(4);
88
- for ($r = 1; $r < 4; $r++) {
89
- for ($c = 0; $c < 4; $c++) $t[$c] = $s[$r][($c + $r) % $Nb]; // shift into temp copy
90
- for ($c = 0; $c < 4; $c++) $s[$r][$c] = $t[$c]; // and copy back
91
- } // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
92
- return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
93
- }
94
-
95
- /**
96
- * Combine bytes of each col of state S [�5.1.3].
97
- * @since 2.8
98
- */
99
- private static function mixColumns($s, $Nb)
100
- {
101
- for ($c = 0; $c < 4; $c++) {
102
- $a = array(4); // 'a' is a copy of the current column from 's'
103
- $b = array(4); // 'b' is a�{02} in GF(2^8)
104
- for ($i = 0; $i < 4; $i++) {
105
- $a[$i] = $s[$i][$c];
106
- $b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
107
- }
108
- // a[n] ^ b[n] is a�{03} in GF(2^8)
109
- $s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
110
- $s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
111
- $s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
112
- $s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
113
- }
114
- return $s;
115
- }
116
-
117
- /**
118
- * Generate Key Schedule from Cipher Key [�5.2].
119
- *
120
- * Perform key expansion on cipher key to generate a key schedule.
121
- *
122
- * @param key cipher key byte-array (16 bytes).
123
- * @return key schedule as 2D byte-array (Nr+1 x Nb bytes).
124
- * @since 2.8
125
- */
126
- public static function keyExpansion($key)
127
- {
128
- $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
129
- $Nk = count($key) / 4; // key length (in words): 4/6/8 for 128/192/256-bit keys
130
- $Nr = $Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
131
-
132
- $w = array();
133
- $temp = array();
134
-
135
- for ($i = 0; $i < $Nk; $i++) {
136
- $r = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
137
- $w[$i] = $r;
138
- }
139
-
140
- for ($i = $Nk; $i < ($Nb * ($Nr + 1)); $i++) {
141
- $w[$i] = array();
142
- for ($t = 0; $t < 4; $t++) $temp[$t] = $w[$i - 1][$t];
143
- if ($i % $Nk == 0) {
144
- $temp = self::subWord(self::rotWord($temp));
145
- for ($t = 0; $t < 4; $t++) $temp[$t] ^= self::$rCon[$i / $Nk][$t];
146
- } else if ($Nk > 6 && $i % $Nk == 4) {
147
- $temp = self::subWord($temp);
148
- }
149
- for ($t = 0; $t < 4; $t++) $w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
150
- }
151
- return $w;
152
- }
153
-
154
- /**
155
- * Apply SBox to 4-byte word w.
156
- * @since 2.8
157
- */
158
- private static function subWord($w)
159
- {
160
- for ($i = 0; $i < 4; $i++) $w[$i] = self::$sBox[$w[$i]];
161
- return $w;
162
- }
163
-
164
- /**
165
- * Rotate 4-byte word w left by one byte.
166
- * @since 2.8
167
- */
168
- private static function rotWord($w)
169
- {
170
- $tmp = $w[0];
171
- for ($i = 0; $i < 3; $i++) $w[$i] = $w[$i + 1];
172
- $w[3] = $tmp;
173
- return $w;
174
- }
175
-
176
- // sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [�5.1.1]
177
- private static $sBox = array(
178
- 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
179
- 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
180
- 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
181
- 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
182
- 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
183
- 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
184
- 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
185
- 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
186
- 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
187
- 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
188
- 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
189
- 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
190
- 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
191
- 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
192
- 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
193
- 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
194
-
195
- // rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [�5.2]
196
- private static $rCon = array(
197
- array(0x00, 0x00, 0x00, 0x00),
198
- array(0x01, 0x00, 0x00, 0x00),
199
- array(0x02, 0x00, 0x00, 0x00),
200
- array(0x04, 0x00, 0x00, 0x00),
201
- array(0x08, 0x00, 0x00, 0x00),
202
- array(0x10, 0x00, 0x00, 0x00),
203
- array(0x20, 0x00, 0x00, 0x00),
204
- array(0x40, 0x00, 0x00, 0x00),
205
- array(0x80, 0x00, 0x00, 0x00),
206
- array(0x1b, 0x00, 0x00, 0x00),
207
- array(0x36, 0x00, 0x00, 0x00));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
 
209
  }
210
 
211
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1
  <?php
2
+ /*
3
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4
+ /*
5
+ AES implementation in PHP */
6
+ /*
7
+ (c) Chris Veness 2005-2014 www.movable-type.co.uk/scripts */
8
+ /*
9
+ Right of free use is granted for all commercial or non-commercial use under CC-BY licence. */
10
+ /*
11
+ No warranty of any form is offered. */
12
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
13
 
14
  /**
22
 
23
  /**
24
  * It will genrate the encryption and decryption for data.
25
+ *
26
  * @since 2.8
27
  */
28
+ class Wcal_Aes {
29
+
30
+ /**
31
+ * AES Cipher function [�5.1]: encrypt 'input' with Rijndael algorithm
32
+ *
33
+ * @param input message as byte-array (16 bytes)
34
+ * @param w key schedule as 2D byte-array (Nr+1 x Nb bytes) -
35
+ * generated from the cipher key by keyExpansion()
36
+ * @return ciphertext as byte-array (16 bytes)
37
+ * @since 2.8
38
+ */
39
+ public static function cipher( $input, $w ) {
40
+ $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
41
+ $Nr = count( $w ) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
42
+ $state = array(); // initialise 4xNb byte-array 'state' with input [�3.4]
43
+ for ( $i = 0; $i < 4 * $Nb;
44
+ $i++ ) {
45
+ $state[ $i % 4 ][ floor( $i / 4 ) ] = $input[ $i ];
46
+ }
47
+
48
+ $state = self::addRoundKey( $state, $w, 0, $Nb );
49
+
50
+ for ( $round = 1; $round < $Nr; $round++ ) { // apply Nr rounds
51
+ $state = self::subBytes( $state, $Nb );
52
+ $state = self::shiftRows( $state, $Nb );
53
+ $state = self::mixColumns( $state, $Nb );
54
+ $state = self::addRoundKey( $state, $w, $round, $Nb );
55
+ }
56
+
57
+ $state = self::subBytes( $state, $Nb );
58
+ $state = self::shiftRows( $state, $Nb );
59
+ $state = self::addRoundKey( $state, $w, $Nr, $Nb );
60
+
61
+ $output = array( 4 * $Nb ); // convert state to 1-d array before returning [�3.4]
62
+ for ( $i = 0; $i < 4 * $Nb;
63
+ $i++ ) {
64
+ $output[ $i ] = $state[ $i % 4 ][ floor( $i / 4 ) ];
65
+ }
66
+ return $output;
67
+ }
68
+ /**
69
+ * Xor Round Key into state S [�5.1.4].
70
+ *
71
+ * @since 2.8
72
+ */
73
+ private static function addRoundKey( $state, $w, $rnd, $Nb ) {
74
+ for ( $r = 0; $r < 4; $r++ ) {
75
+ for ( $c = 0; $c < $Nb;
76
+ $c++ ) {
77
+ $state[ $r ][ $c ] ^= $w[ $rnd * 4 + $c ][ $r ];
78
+ }
79
+ }
80
+ return $state;
81
+ }
82
+
83
+ /**
84
+ * Apply SBox to state S [�5.1.1].
85
+ *
86
+ * @since 2.8
87
+ */
88
+ private static function subBytes( $s, $Nb ) {
89
+ for ( $r = 0; $r < 4; $r++ ) {
90
+ for ( $c = 0; $c < $Nb;
91
+ $c++ ) {
92
+ $s[ $r ][ $c ] = self::$sBox[ $s[ $r ][ $c ] ];
93
+ }
94
+ }
95
+ return $s;
96
+ }
97
+
98
+ /**
99
+ * Shift row r of state S left by r bytes [�5.1.2].
100
+ *
101
+ * @since 2.8
102
+ */
103
+ private static function shiftRows( $s, $Nb ) {
104
+ $t = array( 4 );
105
+ for ( $r = 1; $r < 4; $r++ ) {
106
+ for ( $c = 0; $c < 4;
107
+ $c++ ) {
108
+ $t[ $c ] = $s[ $r ][ ( $c + $r ) % $Nb ]; // shift into temp copy
109
+ }
110
+ for ( $c = 0; $c < 4;
111
+ $c++ ) {
112
+ $s[ $r ][ $c ] = $t[ $c ]; // and copy back
113
+ }
114
+ } // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
115
+ return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
116
+ }
117
+
118
+ /**
119
+ * Combine bytes of each col of state S [�5.1.3].
120
+ *
121
+ * @since 2.8
122
+ */
123
+ private static function mixColumns( $s, $Nb ) {
124
+ for ( $c = 0; $c < 4; $c++ ) {
125
+ $a = array( 4 ); // 'a' is a copy of the current column from 's'
126
+ $b = array( 4 ); // 'b' is a�{02} in GF(2^8)
127
+ for ( $i = 0; $i < 4; $i++ ) {
128
+ $a[ $i ] = $s[ $i ][ $c ];
129
+ $b[ $i ] = $s[ $i ][ $c ] & 0x80 ? $s[ $i ][ $c ] << 1 ^ 0x011b : $s[ $i ][ $c ] << 1;
130
+ }
131
+ // a[n] ^ b[n] is a�{03} in GF(2^8)
132
+ $s[0][ $c ] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
133
+ $s[1][ $c ] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
134
+ $s[2][ $c ] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
135
+ $s[3][ $c ] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
136
+ }
137
+ return $s;
138
+ }
139
+
140
+ /**
141
+ * Generate Key Schedule from Cipher Key [�5.2].
142
+ *
143
+ * Perform key expansion on cipher key to generate a key schedule.
144
+ *
145
+ * @param key cipher key byte-array (16 bytes).
146
+ * @return key schedule as 2D byte-array (Nr+1 x Nb bytes).
147
+ * @since 2.8
148
+ */
149
+ public static function keyExpansion( $key ) {
150
+ $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
151
+ $Nk = count( $key ) / 4; // key length (in words): 4/6/8 for 128/192/256-bit keys
152
+ $Nr = $Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
153
+
154
+ $w = array();
155
+ $temp = array();
156
+
157
+ for ( $i = 0; $i < $Nk; $i++ ) {
158
+ $r = array( $key[ 4 * $i ], $key[ 4 * $i + 1 ], $key[ 4 * $i + 2 ], $key[ 4 * $i + 3 ] );
159
+ $w[ $i ] = $r;
160
+ }
161
+
162
+ for ( $i = $Nk; $i < ( $Nb * ( $Nr + 1 ) ); $i++ ) {
163
+ $w[ $i ] = array();
164
+ for ( $t = 0; $t < 4;
165
+ $t++ ) {
166
+ $temp[ $t ] = $w[ $i - 1 ][ $t ];
167
+ }
168
+ if ( $i % $Nk == 0 ) {
169
+ $temp = self::subWord( self::rotWord( $temp ) );
170
+ for ( $t = 0; $t < 4;
171
+ $t++ ) {
172
+ $temp[ $t ] ^= self::$rCon[ $i / $Nk ][ $t ];
173
+ }
174
+ } elseif ( $Nk > 6 && $i % $Nk == 4 ) {
175
+ $temp = self::subWord( $temp );
176
+ }
177
+ for ( $t = 0; $t < 4;
178
+ $t++ ) {
179
+ $w[ $i ][ $t ] = $w[ $i - $Nk ][ $t ] ^ $temp[ $t ];
180
+ }
181
+ }
182
+ return $w;
183
+ }
184
+
185
+ /**
186
+ * Apply SBox to 4-byte word w.
187
+ *
188
+ * @since 2.8
189
+ */
190
+ private static function subWord( $w ) {
191
+ for ( $i = 0; $i < 4;
192
+ $i++ ) {
193
+ $w[ $i ] = self::$sBox[ $w[ $i ] ];
194
+ }
195
+ return $w;
196
+ }
197
+
198
+ /**
199
+ * Rotate 4-byte word w left by one byte.
200
+ *
201
+ * @since 2.8
202
+ */
203
+ private static function rotWord( $w ) {
204
+ $tmp = $w[0];
205
+ for ( $i = 0; $i < 3;
206
+ $i++ ) {
207
+ $w[ $i ] = $w[ $i + 1 ];
208
+ }
209
+ $w[3] = $tmp;
210
+ return $w;
211
+ }
212
+
213
+ // sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [�5.1.1]
214
+ private static $sBox = array(
215
+ 0x63,
216
+ 0x7c,
217
+ 0x77,
218
+ 0x7b,
219
+ 0xf2,
220
+ 0x6b,
221
+ 0x6f,
222
+ 0xc5,
223
+ 0x30,
224
+ 0x01,
225
+ 0x67,
226
+ 0x2b,
227
+ 0xfe,
228
+ 0xd7,
229
+ 0xab,
230
+ 0x76,
231
+ 0xca,
232
+ 0x82,
233
+ 0xc9,
234
+ 0x7d,
235
+ 0xfa,
236
+ 0x59,
237
+ 0x47,
238
+ 0xf0,
239
+ 0xad,
240
+ 0xd4,
241
+ 0xa2,
242
+ 0xaf,
243
+ 0x9c,
244
+ 0xa4,
245
+ 0x72,
246
+ 0xc0,
247
+ 0xb7,
248
+ 0xfd,
249
+ 0x93,
250
+ 0x26,
251
+ 0x36,
252
+ 0x3f,
253
+ 0xf7,
254
+ 0xcc,
255
+ 0x34,
256
+ 0xa5,
257
+ 0xe5,
258
+ 0xf1,
259
+ 0x71,
260
+ 0xd8,
261
+ 0x31,
262
+ 0x15,
263
+ 0x04,
264
+ 0xc7,
265
+ 0x23,
266
+ 0xc3,
267
+ 0x18,
268
+ 0x96,
269
+ 0x05,
270
+ 0x9a,
271
+ 0x07,
272
+ 0x12,
273
+ 0x80,
274
+ 0xe2,
275
+ 0xeb,
276
+ 0x27,
277
+ 0xb2,
278
+ 0x75,
279
+ 0x09,
280
+ 0x83,
281
+ 0x2c,
282
+ 0x1a,
283
+ 0x1b,
284
+ 0x6e,
285
+ 0x5a,
286
+ 0xa0,
287
+ 0x52,
288
+ 0x3b,
289
+ 0xd6,
290
+ 0xb3,
291
+ 0x29,
292
+ 0xe3,
293
+ 0x2f,
294
+ 0x84,
295
+ 0x53,
296
+ 0xd1,
297
+ 0x00,
298
+ 0xed,
299
+ 0x20,
300
+ 0xfc,
301
+ 0xb1,
302
+ 0x5b,
303
+ 0x6a,
304
+ 0xcb,
305
+ 0xbe,
306
+ 0x39,
307
+ 0x4a,
308
+ 0x4c,
309
+ 0x58,
310
+ 0xcf,
311
+ 0xd0,
312
+ 0xef,
313
+ 0xaa,
314
+ 0xfb,
315
+ 0x43,
316
+ 0x4d,
317
+ 0x33,
318
+ 0x85,
319
+ 0x45,
320
+ 0xf9,
321
+ 0x02,
322
+ 0x7f,
323
+ 0x50,
324
+ 0x3c,
325
+ 0x9f,
326
+ 0xa8,
327
+ 0x51,
328
+ 0xa3,
329
+ 0x40,
330
+ 0x8f,
331
+ 0x92,
332
+ 0x9d,
333
+ 0x38,
334
+ 0xf5,
335
+ 0xbc,
336
+ 0xb6,
337
+ 0xda,
338
+ 0x21,
339
+ 0x10,
340
+ 0xff,
341
+ 0xf3,
342
+ 0xd2,
343
+ 0xcd,
344
+ 0x0c,
345
+ 0x13,
346
+ 0xec,
347
+ 0x5f,
348
+ 0x97,
349
+ 0x44,
350
+ 0x17,
351
+ 0xc4,
352
+ 0xa7,
353
+ 0x7e,
354
+ 0x3d,
355
+ 0x64,
356
+ 0x5d,
357
+ 0x19,
358
+ 0x73,
359
+ 0x60,
360
+ 0x81,
361
+ 0x4f,
362
+ 0xdc,
363
+ 0x22,
364
+ 0x2a,
365
+ 0x90,
366
+ 0x88,
367
+ 0x46,
368
+ 0xee,
369
+ 0xb8,
370
+ 0x14,
371
+ 0xde,
372
+ 0x5e,
373
+ 0x0b,
374
+ 0xdb,
375
+ 0xe0,
376
+ 0x32,
377
+ 0x3a,
378
+ 0x0a,
379
+ 0x49,
380
+ 0x06,
381
+ 0x24,
382
+ 0x5c,
383
+ 0xc2,
384
+ 0xd3,
385
+ 0xac,
386
+ 0x62,
387
+ 0x91,
388
+ 0x95,
389
+ 0xe4,
390
+ 0x79,
391
+ 0xe7,
392
+ 0xc8,
393
+ 0x37,
394
+ 0x6d,
395
+ 0x8d,
396
+ 0xd5,
397
+ 0x4e,
398
+ 0xa9,
399
+ 0x6c,
400
+ 0x56,
401
+ 0xf4,
402
+ 0xea,
403
+ 0x65,
404
+ 0x7a,
405
+ 0xae,
406
+ 0x08,
407
+ 0xba,
408
+ 0x78,
409
+ 0x25,
410
+ 0x2e,
411
+ 0x1c,
412
+ 0xa6,
413
+ 0xb4,
414
+ 0xc6,
415
+ 0xe8,
416
+ 0xdd,
417
+ 0x74,
418
+ 0x1f,
419
+ 0x4b,
420
+ 0xbd,
421
+ 0x8b,
422
+ 0x8a,
423
+ 0x70,
424
+ 0x3e,
425
+ 0xb5,
426
+ 0x66,
427
+ 0x48,
428
+ 0x03,
429
+ 0xf6,
430
+ 0x0e,
431
+ 0x61,
432
+ 0x35,
433
+ 0x57,
434
+ 0xb9,
435
+ 0x86,
436
+ 0xc1,
437
+ 0x1d,
438
+ 0x9e,
439
+ 0xe1,
440
+ 0xf8,
441
+ 0x98,
442
+ 0x11,
443
+ 0x69,
444
+ 0xd9,
445
+ 0x8e,
446
+ 0x94,
447
+ 0x9b,
448
+ 0x1e,
449
+ 0x87,
450
+ 0xe9,
451
+ 0xce,
452
+ 0x55,
453
+ 0x28,
454
+ 0xdf,
455
+ 0x8c,
456
+ 0xa1,
457
+ 0x89,
458
+ 0x0d,
459
+ 0xbf,
460
+ 0xe6,
461
+ 0x42,
462
+ 0x68,
463
+ 0x41,
464
+ 0x99,
465
+ 0x2d,
466
+ 0x0f,
467
+ 0xb0,
468
+ 0x54,
469
+ 0xbb,
470
+ 0x16,
471
+ );
472
+
473
+ // rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [�5.2]
474
+ private static $rCon = array(
475
+ array( 0x00, 0x00, 0x00, 0x00 ),
476
+ array( 0x01, 0x00, 0x00, 0x00 ),
477
+ array( 0x02, 0x00, 0x00, 0x00 ),
478
+ array( 0x04, 0x00, 0x00, 0x00 ),
479
+ array( 0x08, 0x00, 0x00, 0x00 ),
480
+ array( 0x10, 0x00, 0x00, 0x00 ),
481
+ array( 0x20, 0x00, 0x00, 0x00 ),
482
+ array( 0x40, 0x00, 0x00, 0x00 ),
483
+ array( 0x80, 0x00, 0x00, 0x00 ),
484
+ array( 0x1b, 0x00, 0x00, 0x00 ),
485
+ array( 0x36, 0x00, 0x00, 0x00 ),
486
+ );
487
 
488
  }
489
 
490
+ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
includes/classes/class-wcal-dashboard-report.php CHANGED
@@ -503,7 +503,7 @@ if ( ! class_exists( 'Wcal_Dashoard_Report' ) ) {
503
 
504
  foreach ( $get_carts as $cart_value ) {
505
 
506
- if( $cart_value->recovered_cart > 0 ) {
507
  $abandoned_amount += get_post_meta( $cart_value->recovered_cart, '_order_total', true );
508
  $abandoned_count++;
509
  } else {
@@ -512,7 +512,7 @@ if ( ! class_exists( 'Wcal_Dashoard_Report' ) ) {
512
 
513
  if ( isset( $cart_info ) && false !== $cart_info && count( get_object_vars( $cart_info ) ) > 0 ) {
514
  $abandoned_count++;
515
- if( isset( $cart_info->cart ) && count( get_object_vars( $cart_info->cart ) ) > 0 ) {
516
  foreach ( $cart_info->cart as $cart ) {
517
  if ( isset( $cart->line_total ) ) {
518
  $abandoned_amount += $cart->line_total;
503
 
504
  foreach ( $get_carts as $cart_value ) {
505
 
506
+ if ( $cart_value->recovered_cart > 0 ) {
507
  $abandoned_amount += get_post_meta( $cart_value->recovered_cart, '_order_total', true );
508
  $abandoned_count++;
509
  } else {
512
 
513
  if ( isset( $cart_info ) && false !== $cart_info && count( get_object_vars( $cart_info ) ) > 0 ) {
514
  $abandoned_count++;
515
+ if ( isset( $cart_info->cart ) && count( get_object_vars( $cart_info->cart ) ) > 0 ) {
516
  foreach ( $cart_info->cart as $cart ) {
517
  if ( isset( $cart->line_total ) ) {
518
  $abandoned_amount += $cart->line_total;
includes/classes/class-wcal-product-report-table.php CHANGED
@@ -1,8 +1,8 @@
1
- <?php
2
 
3
- if( session_id() === '' ){
4
- //session has not started
5
- session_start();
6
  }
7
  // Load WP_List_Table if not loaded
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
@@ -38,13 +38,13 @@ class WCAL_Product_Report_Table extends WP_List_Table {
38
  public $base_url;
39
 
40
  /**
41
- * Total number of products
42
  *
43
  * @var int
44
  * @since 2.5.3
45
  */
46
  public $total_count;
47
-
48
  /**
49
  * It will add the variable needed for the class.
50
  *
@@ -54,192 +54,198 @@ class WCAL_Product_Report_Table extends WP_List_Table {
54
  public function __construct() {
55
  global $status, $page;
56
  // Set parent defaults
57
- parent::__construct( array(
58
- 'singular' => __( 'product_id', 'woocommerce-abandoned-cart' ), //singular name of the listed records
59
- 'plural' => __( 'product_ids', 'woocommerce-abandoned-cart' ), //plural name of the listed records
60
- 'ajax' => false // Does this table support ajax?
61
- ) );
 
 
62
  $this->base_url = admin_url( 'admin.php?page=woocommerce_ac_page&action=stats' );
63
  }
64
-
65
  /**
66
  * It will prepare the list of the Product reports, like columns, pagination, sortable column, all data
 
67
  * @since 2.5.3
68
  */
69
  public function wcal_product_report_prepare_items() {
70
  $columns = $this->get_columns();
71
- $hidden = array(); // No hidden columns
72
- $data = $this->wcal_product_report_data ();
73
- $total_items = $this->total_count;
74
- $this->items = $data;
75
- $this->_column_headers = array( $columns, $hidden);
76
- $this->set_pagination_args( array(
77
- 'total_items' => $total_items, // WE have to calculate the total number of items
78
- 'per_page' => $this->per_page, // WE have to determine how many items to show on a page
79
- 'total_pages' => ceil( $total_items / $this->per_page ) // WE have to calculate the total number of pages
80
- )
81
- );
 
82
  }
83
-
84
  /**
85
  * It will add the columns product report list.
 
86
  * @return array $columns All columns name.
87
  * @since 2.5.3
88
  */
89
- public function get_columns() {
90
- $columns = array(
91
- 'product_name' => __( 'Product Name', 'woocommerce-abandoned-cart' ),
92
- 'abandoned_number' => __( 'Number of Times Abandoned', 'woocommerce-abandoned-cart' ),
93
- 'recover_number' => __( 'Number of Times Recovered', 'woocommerce-abandoned-cart' )
94
- );
95
- return apply_filters( 'wcal_product_report_columns', $columns );
96
  }
97
-
98
- /**
99
- * It will generate the product list data.
100
- * @globals mixed $wpdb
101
- * @return array $return_product_report_display Key and value of all the columns
102
- * @since 2.5.3
103
- */
104
- public function wcal_product_report_data () {
105
- global $wpdb;
106
- $wcal_class = new woocommerce_abandon_cart_lite ();
 
107
  $per_page = $this->per_page;
108
- $i = 0;
109
- $order = "desc";
110
  $blank_cart_info = '{"cart":[]}';
111
  $blank_cart_info_guest = '[]';
112
  $blank_cart = '""';
113
- $query = "SELECT abandoned_cart_time, abandoned_cart_info, recovered_cart FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE abandoned_cart_info NOT LIKE '%$blank_cart_info%' AND abandoned_cart_info NOT LIKE '$blank_cart_info_guest' AND abandoned_cart_info NOT LIKE '$blank_cart' ORDER BY recovered_cart DESC";
114
  $recover_query = $wpdb->get_results( $query );
115
- $rec_carts_array = array ( );
116
- $recover_product_array = array( );
117
  $return_product_report = array();
118
-
119
- foreach( $recover_query as $recovered_cart_key => $recovered_cart_value ) {
120
- $recovered_cart_info = json_decode( $recovered_cart_value->abandoned_cart_info );
121
- $recovered_cart_dat = json_decode( $recovered_cart_value->recovered_cart);
122
- $cart_update_time = $recovered_cart_value->abandoned_cart_time;
123
- $quantity_total = 0;
124
- $cart_details = new stdClass();
125
- if( isset( $recovered_cart_info->cart ) ){
126
- $cart_details = $recovered_cart_info->cart;
127
- }
128
- if ( count( get_object_vars( $cart_details ) ) > 0) {
129
- foreach ( $cart_details as $k => $v ) {
130
- $quantity_total = $quantity_total + $v->quantity;
131
- }
132
- }
133
-
134
- $ac_cutoff_time = get_option( 'ac_lite_cart_abandoned_time' );
135
- $cut_off_time = $ac_cutoff_time * 60 ;
136
- $current_time = current_time( 'timestamp' );
137
- $compare_time = $current_time - $cart_update_time;
138
- if ( is_array( $recovered_cart_info ) || is_object( $recovered_cart_info ) ) {
139
- foreach ( $recovered_cart_info as $rec_cart_key => $rec_cart_value ) {
140
- foreach ( $rec_cart_value as $rec_product_id_key => $rec_product_id_value ) {
141
- $product_id = $rec_product_id_value->product_id;
142
- if ( $compare_time > $cut_off_time ) {
143
- $rec_carts_array [] = $product_id;
144
- }
145
- if($recovered_cart_dat != 0) {
146
- $recover_product_array[] = $product_id;
147
- }
148
- }
149
- }
150
- }
151
  }
152
-
153
  $count = array_count_values( $rec_carts_array );
154
  $count1 = $count;
155
- $count_new = $wcal_class->bubble_sort_function ( $count1 ,$order );
156
- $recover_cart = "0";
157
  $count_css = 0;
158
- $chunck_array = array_chunk( $count_new,10, true ); // keep True for retaing the Array Index number which is product ids in our case.
159
  $chunck_array_value = array();
160
 
161
- foreach ( $chunck_array as $chunck_array_key => $chunck_array_value ) {
162
- foreach ( $chunck_array_value as $k => $v ) {
163
- $return_product_report[$i] = new stdClass();
164
- $prod_name = get_post( $k );
165
- if ( NULL != $prod_name || '' != $prod_name ) {
166
- $product_name = $prod_name->post_title;
167
- $abandoned_count = $v;
168
- $recover = array_count_values( $recover_product_array );
169
- foreach ( $recover as $ke => $ve ) {
170
- if( array_key_exists ( $ke, $count ) ) {
171
- if ( $ke == $k ) {
172
- $recover_cart = $ve;
173
- }
174
- }
175
- if( ! array_key_exists ( $k, $recover ) ) {
176
- $recover_cart = "0";
177
- }
178
- }
179
-
180
- $return_product_report[ $i ]->product_name = $product_name ;
181
- $return_product_report[ $i ]->abandoned_number = $abandoned_count;
182
- $return_product_report[ $i ]->recover_number = $recover_cart;
183
- $return_product_report[ $i ]->product_id = $k;
184
- $i++;
185
- }
186
- }
187
- }
188
- $this->total_count = count ( $return_product_report ) > 0 ? count ( $return_product_report ) : 0 ;
189
-
190
  // Pagination per page
191
- if( isset( $_GET['paged'] ) && $_GET['paged'] > 1 ) {
192
- $page_number = $_GET['paged'] - 1;
193
- $k = $per_page * $page_number;
194
  } else {
195
- $k = 0;
196
  }
197
  $return_product_report_display = array();
198
- for( $j = $k; $j < ( $k+$per_page ); $j++ ) {
199
- if( isset( $return_product_report[$j] ) ) {
200
- $return_product_report_display[$j] = $return_product_report[$j];
201
- } else {
202
- break;
203
- }
204
- }
205
- return apply_filters( 'wcal_product_report_table_data', $return_product_report_display );
206
  }
207
-
208
  /**
209
  * It will display the data for product column
 
210
  * @param array | object $wcal_sent_emails All data of the list
211
- * @param stirng $column_name Name of the column
212
  * @return string $value Data of the column
213
  * @since 2.5.3
214
  */
215
  public function column_default( $wcal_sent_emails, $column_name ) {
216
- $value = '';
217
- switch ( $column_name ) {
218
-
219
- case 'product_name' :
220
- if( isset( $wcal_sent_emails->product_name ) ) {
221
- $value = "<a href= post.php?post=$wcal_sent_emails->product_id&action=edit title = product name > $wcal_sent_emails->product_name </a>";
222
- }
223
  break;
224
-
225
- case 'abandoned_number' :
226
- if( isset( $wcal_sent_emails->abandoned_number ) ) {
227
- $value = $wcal_sent_emails->abandoned_number;
228
- }
229
  break;
230
-
231
- case 'recover_number' :
232
- if( isset( $wcal_sent_emails->recover_number ) ) {
233
- $value = $wcal_sent_emails->recover_number;
234
- }
235
  break;
236
  default:
237
-
238
  $value = isset( $wcal_sent_emails->$column_name ) ? $wcal_sent_emails->$column_name : '';
239
  break;
240
- }
241
-
242
  return apply_filters( 'wcal_product_report_column_default', $value, $wcal_sent_emails, $column_name );
243
  }
244
  }
245
- ?>
1
+ <?php
2
 
3
+ if ( session_id() === '' ) {
4
+ // session has not started
5
+ session_start();
6
  }
7
  // Load WP_List_Table if not loaded
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
38
  public $base_url;
39
 
40
  /**
41
+ * Total number of products
42
  *
43
  * @var int
44
  * @since 2.5.3
45
  */
46
  public $total_count;
47
+
48
  /**
49
  * It will add the variable needed for the class.
50
  *
54
  public function __construct() {
55
  global $status, $page;
56
  // Set parent defaults
57
+ parent::__construct(
58
+ array(
59
+ 'singular' => __( 'product_id', 'woocommerce-abandoned-cart' ), // singular name of the listed records
60
+ 'plural' => __( 'product_ids', 'woocommerce-abandoned-cart' ), // plural name of the listed records
61
+ 'ajax' => false, // Does this table support ajax?
62
+ )
63
+ );
64
  $this->base_url = admin_url( 'admin.php?page=woocommerce_ac_page&action=stats' );
65
  }
66
+
67
  /**
68
  * It will prepare the list of the Product reports, like columns, pagination, sortable column, all data
69
+ *
70
  * @since 2.5.3
71
  */
72
  public function wcal_product_report_prepare_items() {
73
  $columns = $this->get_columns();
74
+ $hidden = array(); // No hidden columns
75
+ $data = $this->wcal_product_report_data();
76
+ $total_items = $this->total_count;
77
+ $this->items = $data;
78
+ $this->_column_headers = array( $columns, $hidden );
79
+ $this->set_pagination_args(
80
+ array(
81
+ 'total_items' => $total_items, // WE have to calculate the total number of items
82
+ 'per_page' => $this->per_page, // WE have to determine how many items to show on a page
83
+ 'total_pages' => ceil( $total_items / $this->per_page ), // WE have to calculate the total number of pages
84
+ )
85
+ );
86
  }
87
+
88
  /**
89
  * It will add the columns product report list.
90
+ *
91
  * @return array $columns All columns name.
92
  * @since 2.5.3
93
  */
94
+ public function get_columns() {
95
+ $columns = array(
96
+ 'product_name' => __( 'Product Name', 'woocommerce-abandoned-cart' ),
97
+ 'abandoned_number' => __( 'Number of Times Abandoned', 'woocommerce-abandoned-cart' ),
98
+ 'recover_number' => __( 'Number of Times Recovered', 'woocommerce-abandoned-cart' ),
99
+ );
100
+ return apply_filters( 'wcal_product_report_columns', $columns );
101
  }
102
+
103
+ /**
104
+ * It will generate the product list data.
105
+ *
106
+ * @globals mixed $wpdb
107
+ * @return array $return_product_report_display Key and value of all the columns
108
+ * @since 2.5.3
109
+ */
110
+ public function wcal_product_report_data() {
111
+ global $wpdb;
112
+ $wcal_class = new woocommerce_abandon_cart_lite();
113
  $per_page = $this->per_page;
114
+ $i = 0;
115
+ $order = 'desc';
116
  $blank_cart_info = '{"cart":[]}';
117
  $blank_cart_info_guest = '[]';
118
  $blank_cart = '""';
119
+ $query = 'SELECT abandoned_cart_time, abandoned_cart_info, recovered_cart FROM `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE abandoned_cart_info NOT LIKE '%$blank_cart_info%' AND abandoned_cart_info NOT LIKE '$blank_cart_info_guest' AND abandoned_cart_info NOT LIKE '$blank_cart' ORDER BY recovered_cart DESC";
120
  $recover_query = $wpdb->get_results( $query );
121
+ $rec_carts_array = array();
122
+ $recover_product_array = array();
123
  $return_product_report = array();
124
+
125
+ foreach ( $recover_query as $recovered_cart_key => $recovered_cart_value ) {
126
+ $recovered_cart_info = json_decode( $recovered_cart_value->abandoned_cart_info );
127
+ $recovered_cart_dat = json_decode( $recovered_cart_value->recovered_cart );
128
+ $cart_update_time = $recovered_cart_value->abandoned_cart_time;
129
+ $quantity_total = 0;
130
+ $cart_details = new stdClass();
131
+ if ( isset( $recovered_cart_info->cart ) ) {
132
+ $cart_details = $recovered_cart_info->cart;
133
+ }
134
+ if ( count( get_object_vars( $cart_details ) ) > 0 ) {
135
+ foreach ( $cart_details as $k => $v ) {
136
+ $quantity_total = $quantity_total + $v->quantity;
137
+ }
138
+ }
139
+
140
+ $ac_cutoff_time = get_option( 'ac_lite_cart_abandoned_time' );
141
+ $cut_off_time = $ac_cutoff_time * 60;
142
+ $current_time = current_time( 'timestamp' );
143
+ $compare_time = $current_time - $cart_update_time;
144
+ if ( is_array( $recovered_cart_info ) || is_object( $recovered_cart_info ) ) {
145
+ foreach ( $recovered_cart_info as $rec_cart_key => $rec_cart_value ) {
146
+ foreach ( $rec_cart_value as $rec_product_id_key => $rec_product_id_value ) {
147
+ $product_id = $rec_product_id_value->product_id;
148
+ if ( $compare_time > $cut_off_time ) {
149
+ $rec_carts_array [] = $product_id;
150
+ }
151
+ if ( $recovered_cart_dat != 0 ) {
152
+ $recover_product_array[] = $product_id;
153
+ }
154
+ }
155
+ }
156
+ }
157
  }
158
+
159
  $count = array_count_values( $rec_carts_array );
160
  $count1 = $count;
161
+ $count_new = $wcal_class->bubble_sort_function( $count1, $order );
162
+ $recover_cart = '0';
163
  $count_css = 0;
164
+ $chunck_array = array_chunk( $count_new, 10, true ); // keep True for retaing the Array Index number which is product ids in our case.
165
  $chunck_array_value = array();
166
 
167
+ foreach ( $chunck_array as $chunck_array_key => $chunck_array_value ) {
168
+ foreach ( $chunck_array_value as $k => $v ) {
169
+ $return_product_report[ $i ] = new stdClass();
170
+ $prod_name = get_post( $k );
171
+ if ( null != $prod_name || '' != $prod_name ) {
172
+ $product_name = $prod_name->post_title;
173
+ $abandoned_count = $v;
174
+ $recover = array_count_values( $recover_product_array );
175
+ foreach ( $recover as $ke => $ve ) {
176
+ if ( array_key_exists( $ke, $count ) ) {
177
+ if ( $ke == $k ) {
178
+ $recover_cart = $ve;
179
+ }
180
+ }
181
+ if ( ! array_key_exists( $k, $recover ) ) {
182
+ $recover_cart = '0';
183
+ }
184
+ }
185
+
186
+ $return_product_report[ $i ]->product_name = $product_name;
187
+ $return_product_report[ $i ]->abandoned_number = $abandoned_count;
188
+ $return_product_report[ $i ]->recover_number = $recover_cart;
189
+ $return_product_report[ $i ]->product_id = $k;
190
+ $i++;
191
+ }
192
+ }
193
+ }
194
+ $this->total_count = count( $return_product_report ) > 0 ? count( $return_product_report ) : 0;
195
+
196
  // Pagination per page
197
+ if ( isset( $_GET['paged'] ) && $_GET['paged'] > 1 ) {
198
+ $page_number = $_GET['paged'] - 1;
199
+ $k = $per_page * $page_number;
200
  } else {
201
+ $k = 0;
202
  }
203
  $return_product_report_display = array();
204
+ for ( $j = $k; $j < ( $k + $per_page ); $j++ ) {
205
+ if ( isset( $return_product_report[ $j ] ) ) {
206
+ $return_product_report_display[ $j ] = $return_product_report[ $j ];
207
+ } else {
208
+ break;
209
+ }
210
+ }
211
+ return apply_filters( 'wcal_product_report_table_data', $return_product_report_display );
212
  }
213
+
214
  /**
215
  * It will display the data for product column
216
+ *
217
  * @param array | object $wcal_sent_emails All data of the list
218
+ * @param stirng $column_name Name of the column
219
  * @return string $value Data of the column
220
  * @since 2.5.3
221
  */
222
  public function column_default( $wcal_sent_emails, $column_name ) {
223
+ $value = '';
224
+ switch ( $column_name ) {
225
+
226
+ case 'product_name':
227
+ if ( isset( $wcal_sent_emails->product_name ) ) {
228
+ $value = "<a href= post.php?post=$wcal_sent_emails->product_id&action=edit title = product name > $wcal_sent_emails->product_name </a>";
229
+ }
230
  break;
231
+
232
+ case 'abandoned_number':
233
+ if ( isset( $wcal_sent_emails->abandoned_number ) ) {
234
+ $value = $wcal_sent_emails->abandoned_number;
235
+ }
236
  break;
237
+
238
+ case 'recover_number':
239
+ if ( isset( $wcal_sent_emails->recover_number ) ) {
240
+ $value = $wcal_sent_emails->recover_number;
241
+ }
242
  break;
243
  default:
 
244
  $value = isset( $wcal_sent_emails->$column_name ) ? $wcal_sent_emails->$column_name : '';
245
  break;
246
+ }
247
+
248
  return apply_filters( 'wcal_product_report_column_default', $value, $wcal_sent_emails, $column_name );
249
  }
250
  }
251
+
includes/classes/class-wcal-recover-orders-table.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
 
3
  // Load WP_List_Table if not loaded
4
  if ( ! class_exists( 'WP_List_Table' ) ) {
@@ -39,8 +39,8 @@ class wcal_Recover_Orders_Table extends WP_List_Table {
39
  * @since 2.5.2
40
  */
41
  public $total_count;
42
-
43
-
44
  /**
45
  * Total number of abandoned orders
46
  *
@@ -48,7 +48,7 @@ class wcal_Recover_Orders_Table extends WP_List_Table {
48
  * @since 2.5.2
49
  */
50
  public $total_abandoned_cart_count;
51
-
52
  /**
53
  * Total amount of abandoned orders
54
  *
@@ -56,7 +56,7 @@ class wcal_Recover_Orders_Table extends WP_List_Table {
56
  * @since 2.5.2
57
  */
58
  public $total_order_amount;
59
-
60
  /**
61
  * Total number recovered orders
62
  *
@@ -64,16 +64,16 @@ class wcal_Recover_Orders_Table extends WP_List_Table {
64
  * @since 2.5.2
65
  */
66
  public $recovered_item;
67
-
68
  /**
69
  * Total number recovred orders total
70
  *
71
  * @var int
72
  * @since 2.5.2
73
  */
74
- public $total_recover_amount;
75
 
76
- /**
77
  * It will add the variable needed for the class.
78
  *
79
  * @see WP_List_Table::__construct()
@@ -82,394 +82,405 @@ class wcal_Recover_Orders_Table extends WP_List_Table {
82
  public function __construct() {
83
  global $status, $page;
84
  // Set parent defaults
85
- parent::__construct( array(
86
- 'singular' => __( 'rec_abandoned_id', 'woocommerce-abandoned-cart' ), //singular name of the listed records
87
- 'plural' => __( 'rec_abandoned_ids', 'woocommerce-abandoned-cart' ), //plural name of the listed records
88
- 'ajax' => false // Does this table support ajax?
89
- ) );
90
- $this->base_url = admin_url( 'admin.php?page=woocommerce_ac_page&action=stats' );
 
 
91
  }
92
-
93
  /**
94
  * It will prepare the list of the recovered carts, like columns, pagination, sortable column, all data.
 
95
  * @since 2.5.2
96
  */
97
- public function wcal_recovered_orders_prepare_items() {
98
  $columns = $this->get_columns();
99
  $hidden = array(); // No hidden columns
100
  $sortable = $this->recovered_orders_get_sortable_columns();
101
- $data = $this->wcal_recovered_orders_data();
102
  $total_items = $this->total_count;
103
  $total_abandoned_cart_count = $this->total_abandoned_cart_count;
104
  $total_order_amount = $this->total_order_amount;
105
  $total_recover_amount = $this->total_recover_amount;
106
  $recovered_item = $this->recovered_item;
107
- $this->items = $data;
108
- $this->_column_headers = array( $columns, $hidden, $sortable);
109
- $this->set_pagination_args( array(
110
- 'total_items' => $total_items, // WE have to calculate the total number of items
111
- 'per_page' => $this->per_page, // WE have to determine how many items to show on a page
112
- 'total_pages' => ceil( $total_items / $this->per_page ) // WE have to calculate the total number of pages
113
- )
 
114
  );
115
  }
116
-
117
  /**
118
  * It will add the columns recovered orders list.
 
119
  * @return array $columns All columns name.
120
  * @since 2.5.2
121
  */
122
- public function get_columns() {
123
- $columns = array(
124
- 'user_name' => __( 'Customer Name', 'woocommerce-abandoned-cart' ),
125
- 'user_email_id' => __( 'Email Address', 'woocommerce-abandoned-cart' ),
126
- 'created_on' => __( 'Cart Abandoned Date', 'woocommerce-abandoned-cart' ),
127
- 'recovered_date' => __( 'Cart Recovered Date' , 'woocommerce-abandoned-cart'),
128
- 'order_total' => __( 'Order Total', 'woocommerce-abandoned-cart' )
129
- );
130
- return apply_filters( 'wcal_recovered_orders_columns', $columns );
131
  }
132
-
133
  /**
134
  * We can mention on which column we need the sorting. Here, Abandoned cart date and recovered date.
 
135
  * @return array $columns Name of the column
136
  * @since 2.5.2
137
  */
138
  public function recovered_orders_get_sortable_columns() {
139
  $columns = array(
140
- 'created_on' => array( 'created_on', false ),
141
- 'recovered_date' => array( 'recovered_date',false)
142
  );
143
  return apply_filters( 'wcal_templates_sortable_columns', $columns );
144
  }
145
-
146
  /**
147
- * Render the user name Column.
148
  * We will add the view detials hover link.
 
149
  * @since 2.5.2
150
- * @param array $recovered_orders_row_info Contains all the data of the recovered order row
151
  * @return string $value shown in the User name
152
- *
153
  */
154
- public function column_user_name( $recovered_orders_row_info ) {
155
- $row_actions = array();
156
- $value = '';
157
- $recovered_id = 0;
158
-
159
- if( isset( $recovered_orders_row_info->user_name ) ) {
160
- $recovered_id = $recovered_orders_row_info->recovered_id ;
161
- $row_actions['view_details'] = "<a target=_blank href = post.php?post=$recovered_id&action=edit>". __( 'View Details', 'woocommerce-abandoned-cart' )."</a>";
162
- $user_name = $recovered_orders_row_info->user_name;
163
- $value = $user_name . $this->row_actions( $row_actions );
164
- }
165
- return apply_filters( 'wcal_recovered_orders_single_column', $value, $recovered_id, 'email' );
166
  }
167
-
168
- /**
169
- * It will generate the recovered cart list data.
170
- * @globals mixed $wpdb
171
- * @globals mixed $woocommerce
172
- * @return array $return_recovered_orders_display Key and value of all the columns
173
- * @since 2.5.2
174
- */
175
- public function wcal_recovered_orders_data() {
176
- global $wpdb, $woocommerce;
177
- $wcal_class = new woocommerce_abandon_cart_lite ();
178
- $number_decimal = wc_get_price_decimals();
179
-
 
180
  if ( isset( $_POST['duration_select'] ) ) {
181
- $duration_range = $_POST['duration_select'];
182
- }
183
- else {
184
- $duration_range = "";
185
- }
186
-
187
- if ( $duration_range == "" ) {
188
- if ( isset( $_GET['duration_select'] ) ) {
189
- $duration_range = $_GET['duration_select'];
190
- }
191
  }
192
-
193
- if ( $duration_range == "" ) {
194
- $duration_range = "last_seven";
 
 
195
  }
196
- else {
197
- $duration_range = "";
 
 
 
198
  }
199
-
200
  if ( isset( $_POST['start_date'] ) ) {
201
- $start_date_range = $_POST['start_date'];
 
 
202
  }
203
- else {
204
- $start_date_range = "";
 
205
  }
206
-
207
- if ( $start_date_range == "" ) {
208
- $start_date_range = $wcal_class->start_end_dates[$duration_range]['start_date'];
 
 
209
  }
210
-
211
- if ( isset( $_POST['end_date'] ) ) $end_date_range = $_POST['end_date'];
212
- else $end_date_range = "";
213
-
214
- if ( $end_date_range == "" ) {
215
- $end_date_range = $wcal_class->start_end_dates[$duration_range]['end_date'];
216
  }
217
-
218
- $start_date = strtotime( $start_date_range." 00:01:01" );
219
- $end_date = strtotime( $end_date_range." 23:59:59" );
220
  $ac_cutoff_time = get_option( 'ac_lite_cart_abandoned_time' );
221
  $cut_off_time = $ac_cutoff_time * 60;
222
  $current_time = current_time( 'timestamp' );
223
  $compare_time = $current_time - $cut_off_time;
224
  $blank_cart_info = '{"cart":[]}';
225
  $blank_cart_info_guest = '[]';
226
- $blank_cart = '""';
227
-
228
- $query_ac = "SELECT * FROM " . $wpdb->prefix . "ac_abandoned_cart_history_lite
229
  WHERE abandoned_cart_time >= %d AND abandoned_cart_time <= %d AND recovered_cart > 0 AND abandoned_cart_time <= '$compare_time' AND abandoned_cart_info NOT LIKE '%$blank_cart_info%' AND abandoned_cart_info NOT LIKE '$blank_cart_info_guest' AND abandoned_cart_info NOT LIKE '$blank_cart' ORDER BY recovered_cart desc";
230
- $ac_results = $wpdb->get_results( $wpdb->prepare( $query_ac, $start_date, $end_date ) );
231
-
232
- $query_ac_carts = "SELECT * FROM " . $wpdb->prefix . "ac_abandoned_cart_history_lite
233
  WHERE abandoned_cart_time >= %d AND abandoned_cart_time <= %d AND abandoned_cart_time <= '$compare_time' AND abandoned_cart_info NOT LIKE '%$blank_cart_info%' AND abandoned_cart_info NOT LIKE '$blank_cart_info_guest' AND abandoned_cart_info NOT LIKE '$blank_cart' AND cart_ignored <> '1'";
234
  $ac_carts_results = $wpdb->get_results( $wpdb->prepare( $query_ac_carts, $start_date, $end_date ) );
235
-
236
- $recovered_item = $recovered_total = $count_carts = $total_value = $order_total = 0;
237
  $return_recovered_orders = array();
238
- $per_page = $this->per_page;
239
- $i = 0;
240
- foreach ( $ac_carts_results as $key => $value ) {
241
- $count_carts += 1;
242
- $cart_detail = json_decode( $value->abandoned_cart_info );
243
- $product_details = new stdClass();
244
- if( isset( $cart_detail->cart ) ) {
245
- $product_details = $cart_detail->cart;
246
- }
247
- $line_total = 0;
248
-
249
- if ( false != $product_details && is_object( $product_details ) && count( get_object_vars( $product_details ) ) > 0 ) {
250
- foreach ( $product_details as $k => $v ) {
251
- if( $v->line_subtotal_tax != 0 && $v->line_subtotal_tax > 0 ) {
252
- $line_total = $line_total + $v->line_total + $v->line_subtotal_tax;
253
- } else {
254
- $line_total = $line_total + $v->line_total;
255
- }
256
- }
257
- }
258
- $total_value += $line_total;
259
  }
260
- //$total_value = wc_price( $total_value );
261
  $this->total_order_amount = $total_value;
262
  $this->total_abandoned_cart_count = $count_carts;
263
  $recovered_order_total = 0;
264
  $this->total_recover_amount = round( $recovered_order_total, $number_decimal );
265
  $this->recovered_item = 0;
266
- $table_data = "";
267
-
268
  foreach ( $ac_results as $key => $value ) {
269
- if( $value->recovered_cart != 0 ) {
270
- $return_recovered_orders[$i] = new stdClass();
271
- $recovered_id = $value->recovered_cart;
272
- $rec_order = get_post_meta( $recovered_id );
273
- $woo_order = array();
274
- try{
275
- $woo_order = wc_get_order( $recovered_id );
276
- if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
277
- $order = get_post( $recovered_id );
278
- $recovered_date = strtotime ( $order->post_date );
 
 
 
 
 
279
  $recovered_date_format = date_i18n( get_option( 'date_format' ), $recovered_date );
280
- $recovered_time_format = date_i18n( get_option( 'time_format' ), $recovered_date );
281
  $recovered_date_new = $recovered_date_format . ' ' . $recovered_time_format;
282
- } else {
283
- $recovered_date = strtotime( $woo_order->order_date );
284
- $recovered_date_format = date_i18n( get_option( 'date_format' ), $recovered_date );
285
- $recovered_time_format = date_i18n( get_option( 'time_format' ), $recovered_date );
286
- $recovered_date_new = $recovered_date_format . ' ' . $recovered_time_format;
287
- }
288
- $recovered_item += 1;
289
-
290
- if ( isset( $rec_order ) && $rec_order != false ) {
291
- $recovered_total += $rec_order['_order_total'][0];
292
- }
293
- $date_format = date_i18n( get_option( 'date_format' ), $value->abandoned_cart_time );
294
- $time_format = date_i18n( get_option( 'time_format' ), $value->abandoned_cart_time );
295
- $abandoned_date = $date_format . ' ' . $time_format;
296
- $abandoned_order_id = $value->id;
297
- $billing_first_name = $billing_last_name = $billing_email = '';
298
- $recovered_order_total = 0;
299
-
300
- if( isset( $rec_order['_billing_first_name'][0] ) ) {
301
- $billing_first_name = $rec_order['_billing_first_name'][0];
302
- }
303
-
304
- if( isset( $rec_order['_billing_last_name'][0] ) ) {
305
- $billing_last_name = $rec_order['_billing_last_name'][0];
306
- }
307
-
308
- if( isset( $rec_order['_billing_email'][0] ) ) {
309
- $billing_email = $rec_order['_billing_email'][0];
310
- }
311
-
312
- if( isset( $rec_order['_order_total'][0] ) ) {
313
- $recovered_order_total = $rec_order['_order_total'][0];
314
- }
315
-
316
- $return_recovered_orders[ $i ]->user_name = $billing_first_name . " " . $billing_last_name ;
317
- $return_recovered_orders[ $i ]->user_email_id = $billing_email;
318
- $return_recovered_orders[ $i ]->created_on = $abandoned_date;
319
- $return_recovered_orders[ $i ]->recovered_date = $recovered_date_new;
320
- $return_recovered_orders[ $i ]->recovered_id = $recovered_id;
321
- $return_recovered_orders[ $i ]->recover_order_date = $recovered_date;
322
- $return_recovered_orders[ $i ]->abandoned_date = $value->abandoned_cart_time;
323
- $return_recovered_orders[ $i ]->order_total = wc_price($recovered_order_total);
324
-
325
- $this->recovered_item = $recovered_item;
326
- $this->total_recover_amount = round( ( $recovered_order_total + $this->total_recover_amount ), $number_decimal );
327
- $i++;
328
- }catch (Exception $e){
329
-
330
- }
331
-
332
- }
333
  }
334
- $this->total_order_amount = wc_price( $this->total_order_amount + $this->total_recover_amount );
335
  $this->total_abandoned_cart_count = $this->total_abandoned_cart_count + $this->recovered_item;
336
- $templates_count = count( $return_recovered_orders );
337
- $this->total_count = $templates_count;
338
- // sort for order date
339
- if( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'created_on' ) {
340
- if( isset( $_GET['order'] ) && $_GET['order'] == 'asc' ) {
341
- usort( $return_recovered_orders, array( __CLASS__ , "wcal_class_recovered_created_on_asc" ) );
342
  } else {
343
- usort( $return_recovered_orders, array( __CLASS__ , "wcal_class_recovered_created_on_dsc" ) );
344
  }
345
  }
346
  // sort for customer name
347
- else if( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'recovered_date' ) {
348
- if( isset( $_GET['order'] ) && $_GET['order'] == 'asc' ) {
349
- usort( $return_recovered_orders, array( __CLASS__ , "wcal_class_recovered_date_asc" ) );
350
  } else {
351
- usort( $return_recovered_orders, array( __CLASS__ , "wcal_class_recovered_date_dsc" ) );
352
  }
353
  }
354
  // Pagination per page
355
- if( isset( $_GET['paged'] ) && $_GET['paged'] > 1 ) {
356
- $page_number = $_GET['paged'] - 1;
357
- $k = $per_page * $page_number;
358
  } else {
359
- $k = 0;
360
  }
361
  $return_recovered_orders_display = array();
362
- for( $j = $k; $j < ( $k+$per_page ); $j++ ) {
363
- if( isset( $return_recovered_orders[$j] ) ) {
364
- $return_recovered_orders_display[$j] = $return_recovered_orders[$j];
365
- } else {
366
- break;
367
- }
368
- }
369
- return apply_filters( 'wcal_recovered_orders_table_data', $return_recovered_orders_display );
370
  }
371
-
372
  /**
373
  * It will sort the ascending data based on the abandoned cart date.
 
374
  * @param array | object $value1 All data of the list
375
  * @param array | object $value2 All data of the list
376
- * @return timestamp
377
  * @since 2.5.2
378
  */
379
- function wcal_class_recovered_created_on_asc( $value1,$value2 ) {
380
- return $value1->abandoned_date - $value2->abandoned_date;
381
  }
382
-
383
  /**
384
  * It will sort the descending data based on the abandoned cart date.
 
385
  * @param array | object $value1 All data of the list
386
  * @param array | object $value2 All data of the list
387
- * @return timestamp
388
  * @since 2.5.2
389
  */
390
- function wcal_class_recovered_created_on_dsc( $value1,$value2 ) {
391
- return $value2->abandoned_date - $value1->abandoned_date;
392
  }
393
 
394
  /**
395
  * It will sort the ascending data based on the recovered cart date.
 
396
  * @param array | object $value1 All data of the list
397
  * @param array | object $value2 All data of the list
398
  * @globals mixed $woocommerce
399
- * @return timestamp
400
  * @since 2.5.2
401
- */
402
- function wcal_class_recovered_date_asc( $value1,$value2 ) {
403
 
404
  global $woocommerce;
405
- if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
406
- $value1 = $value1->recover_order_date;
407
- $value2 = $value2->recover_order_date;
408
-
409
  $value1->recover_order_date = $value1->getTimestamp();
410
  $value2->recover_order_date = $value2->getTimestamp();
411
  }
412
- return $value1->recover_order_date - $value2->recover_order_date;
413
  }
414
 
415
  /**
416
  * It will sort the descending data based on the recovered cart date.
 
417
  * @param array | object $value1 All data of the list
418
  * @param array | object $value2 All data of the list
419
  * @globals mixed $woocommerce
420
- * @return timestamp
421
  * @since 2.5.2
422
  */
423
-
424
- function wcal_class_recovered_date_dsc( $value1,$value2 ) {
425
  global $woocommerce;
426
- if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
427
- $value1 = $value1->recover_order_date;
428
- $value2 = $value2->recover_order_date;
429
-
430
  $value1->recover_order_date = $value1->getTimestamp();
431
  $value2->recover_order_date = $value2->getTimestamp();
432
  }
433
- return $value2->recover_order_date - $value1->recover_order_date;
434
  }
435
-
436
  /**
437
  * It will display the data for the recovered column.
 
438
  * @param array | object $wcal_abandoned_orders All data of the list
439
- * @param stirng $column_name Name of the column
440
  * @return string $value Data of the column
441
  * @since 2.5.2
442
  */
443
  public function column_default( $wcal_abandoned_orders, $column_name ) {
444
- $value = '';
445
- switch ( $column_name ) {
446
- case 'user_email_id' :
447
- if( isset( $wcal_abandoned_orders->user_email_id ) ) {
448
-
449
- $user_email_id = "<a href= mailto:$wcal_abandoned_orders->user_email_id>". $wcal_abandoned_orders->user_email_id."</a>" ;
450
- $value = $user_email_id;
451
- }
 
 
 
 
 
452
  break;
453
- case 'created_on' :
454
- if( isset( $wcal_abandoned_orders->created_on ) ) {
455
- $value = $wcal_abandoned_orders->created_on;
456
- }
457
  break;
458
- case 'recovered_date' :
459
- if( isset( $wcal_abandoned_orders->recovered_date ) ) {
460
- $value = $wcal_abandoned_orders->recovered_date;
461
- }
462
  break;
463
- case 'order_total' :
464
- if( isset( $wcal_abandoned_orders->order_total ) ) {
465
- $value = $wcal_abandoned_orders->order_total;
466
- }
467
- break;
468
- default:
469
  $value = isset( $wcal_abandoned_orders->$column_name ) ? $wcal_abandoned_orders->$column_name : '';
470
  break;
471
- }
472
  return apply_filters( 'wcal_recovered_orders_column_default', $value, $wcal_abandoned_orders, $column_name );
473
  }
474
  }
475
- ?>
1
+ <?php
2
 
3
  // Load WP_List_Table if not loaded
4
  if ( ! class_exists( 'WP_List_Table' ) ) {
39
  * @since 2.5.2
40
  */
41
  public $total_count;
42
+
43
+
44
  /**
45
  * Total number of abandoned orders
46
  *
48
  * @since 2.5.2
49
  */
50
  public $total_abandoned_cart_count;
51
+
52
  /**
53
  * Total amount of abandoned orders
54
  *
56
  * @since 2.5.2
57
  */
58
  public $total_order_amount;
59
+
60
  /**
61
  * Total number recovered orders
62
  *
64
  * @since 2.5.2
65
  */
66
  public $recovered_item;
67
+
68
  /**
69
  * Total number recovred orders total
70
  *
71
  * @var int
72
  * @since 2.5.2
73
  */
74
+ public $total_recover_amount;
75
 
76
+ /**
77
  * It will add the variable needed for the class.
78
  *
79
  * @see WP_List_Table::__construct()
82
  public function __construct() {
83
  global $status, $page;
84
  // Set parent defaults
85
+ parent::__construct(
86
+ array(
87
+ 'singular' => __( 'rec_abandoned_id', 'woocommerce-abandoned-cart' ), // singular name of the listed records
88
+ 'plural' => __( 'rec_abandoned_ids', 'woocommerce-abandoned-cart' ), // plural name of the listed records
89
+ 'ajax' => false, // Does this table support ajax?
90
+ )
91
+ );
92
+ $this->base_url = admin_url( 'admin.php?page=woocommerce_ac_page&action=stats' );
93
  }
94
+
95
  /**
96
  * It will prepare the list of the recovered carts, like columns, pagination, sortable column, all data.
97
+ *
98
  * @since 2.5.2
99
  */
100
+ public function wcal_recovered_orders_prepare_items() {
101
  $columns = $this->get_columns();
102
  $hidden = array(); // No hidden columns
103
  $sortable = $this->recovered_orders_get_sortable_columns();
104
+ $data = $this->wcal_recovered_orders_data();
105
  $total_items = $this->total_count;
106
  $total_abandoned_cart_count = $this->total_abandoned_cart_count;
107
  $total_order_amount = $this->total_order_amount;
108
  $total_recover_amount = $this->total_recover_amount;
109
  $recovered_item = $this->recovered_item;
110
+ $this->items = $data;
111
+ $this->_column_headers = array( $columns, $hidden, $sortable );
112
+ $this->set_pagination_args(
113
+ array(
114
+ 'total_items' => $total_items, // WE have to calculate the total number of items
115
+ 'per_page' => $this->per_page, // WE have to determine how many items to show on a page
116
+ 'total_pages' => ceil( $total_items / $this->per_page ), // WE have to calculate the total number of pages
117
+ )
118
  );
119
  }
120
+
121
  /**
122
  * It will add the columns recovered orders list.
123
+ *
124
  * @return array $columns All columns name.
125
  * @since 2.5.2
126
  */
127
+ public function get_columns() {
128
+ $columns = array(
129
+ 'user_name' => __( 'Customer Name', 'woocommerce-abandoned-cart' ),
130
+ 'user_email_id' => __( 'Email Address', 'woocommerce-abandoned-cart' ),
131
+ 'created_on' => __( 'Cart Abandoned Date', 'woocommerce-abandoned-cart' ),
132
+ 'recovered_date' => __( 'Cart Recovered Date', 'woocommerce-abandoned-cart' ),
133
+ 'order_total' => __( 'Order Total', 'woocommerce-abandoned-cart' ),
134
+ );
135
+ return apply_filters( 'wcal_recovered_orders_columns', $columns );
136
  }
137
+
138
  /**
139
  * We can mention on which column we need the sorting. Here, Abandoned cart date and recovered date.
140
+ *
141
  * @return array $columns Name of the column
142
  * @since 2.5.2
143
  */
144
  public function recovered_orders_get_sortable_columns() {
145
  $columns = array(
146
+ 'created_on' => array( 'created_on', false ),
147
+ 'recovered_date' => array( 'recovered_date', false ),
148
  );
149
  return apply_filters( 'wcal_templates_sortable_columns', $columns );
150
  }
151
+
152
  /**
153
+ * Render the user name Column.
154
  * We will add the view detials hover link.
155
+ *
156
  * @since 2.5.2
157
+ * @param array $recovered_orders_row_info Contains all the data of the recovered order row
158
  * @return string $value shown in the User name
 
159
  */
160
+ public function column_user_name( $recovered_orders_row_info ) {
161
+ $row_actions = array();
162
+ $value = '';
163
+ $recovered_id = 0;
164
+
165
+ if ( isset( $recovered_orders_row_info->user_name ) ) {
166
+ $recovered_id = $recovered_orders_row_info->recovered_id;
167
+ $row_actions['view_details'] = "<a target=_blank href = post.php?post=$recovered_id&action=edit>" . __( 'View Details', 'woocommerce-abandoned-cart' ) . '</a>';
168
+ $user_name = $recovered_orders_row_info->user_name;
169
+ $value = $user_name . $this->row_actions( $row_actions );
170
+ }
171
+ return apply_filters( 'wcal_recovered_orders_single_column', $value, $recovered_id, 'email' );
172
  }
173
+
174
+ /**
175
+ * It will generate the recovered cart list data.
176
+ *
177
+ * @globals mixed $wpdb
178
+ * @globals mixed $woocommerce
179
+ * @return array $return_recovered_orders_display Key and value of all the columns
180
+ * @since 2.5.2
181
+ */
182
+ public function wcal_recovered_orders_data() {
183
+ global $wpdb, $woocommerce;
184
+ $wcal_class = new woocommerce_abandon_cart_lite();
185
+ $number_decimal = wc_get_price_decimals();
186
+
187
  if ( isset( $_POST['duration_select'] ) ) {
188
+ $duration_range = $_POST['duration_select'];
189
+ } else {
190
+ $duration_range = '';
 
 
 
 
 
 
 
191
  }
192
+
193
+ if ( $duration_range == '' ) {
194
+ if ( isset( $_GET['duration_select'] ) ) {
195
+ $duration_range = $_GET['duration_select'];
196
+ }
197
  }
198
+
199
+ if ( $duration_range == '' ) {
200
+ $duration_range = 'last_seven';
201
+ } else {
202
+ $duration_range = '';
203
  }
204
+
205
  if ( isset( $_POST['start_date'] ) ) {
206
+ $start_date_range = $_POST['start_date'];
207
+ } else {
208
+ $start_date_range = '';
209
  }
210
+
211
+ if ( $start_date_range == '' ) {
212
+ $start_date_range = $wcal_class->start_end_dates[ $duration_range ]['start_date'];
213
  }
214
+
215
+ if ( isset( $_POST['end_date'] ) ) {
216
+ $end_date_range = $_POST['end_date'];
217
+ } else {
218
+ $end_date_range = '';
219
  }
220
+
221
+ if ( $end_date_range == '' ) {
222
+ $end_date_range = $wcal_class->start_end_dates[ $duration_range ]['end_date'];
 
 
 
223
  }
224
+
225
+ $start_date = strtotime( $start_date_range . ' 00:01:01' );
226
+ $end_date = strtotime( $end_date_range . ' 23:59:59' );
227
  $ac_cutoff_time = get_option( 'ac_lite_cart_abandoned_time' );
228
  $cut_off_time = $ac_cutoff_time * 60;
229
  $current_time = current_time( 'timestamp' );
230
  $compare_time = $current_time - $cut_off_time;
231
  $blank_cart_info = '{"cart":[]}';
232
  $blank_cart_info_guest = '[]';
233
+ $blank_cart = '""';
234
+
235
+ $query_ac = 'SELECT * FROM ' . $wpdb->prefix . "ac_abandoned_cart_history_lite
236
  WHERE abandoned_cart_time >= %d AND abandoned_cart_time <= %d AND recovered_cart > 0 AND abandoned_cart_time <= '$compare_time' AND abandoned_cart_info NOT LIKE '%$blank_cart_info%' AND abandoned_cart_info NOT LIKE '$blank_cart_info_guest' AND abandoned_cart_info NOT LIKE '$blank_cart' ORDER BY recovered_cart desc";
237
+ $ac_results = $wpdb->get_results( $wpdb->prepare( $query_ac, $start_date, $end_date ) );
238
+
239
+ $query_ac_carts = 'SELECT * FROM ' . $wpdb->prefix . "ac_abandoned_cart_history_lite
240
  WHERE abandoned_cart_time >= %d AND abandoned_cart_time <= %d AND abandoned_cart_time <= '$compare_time' AND abandoned_cart_info NOT LIKE '%$blank_cart_info%' AND abandoned_cart_info NOT LIKE '$blank_cart_info_guest' AND abandoned_cart_info NOT LIKE '$blank_cart' AND cart_ignored <> '1'";
241
  $ac_carts_results = $wpdb->get_results( $wpdb->prepare( $query_ac_carts, $start_date, $end_date ) );
242
+
243
+ $recovered_item = $recovered_total = $count_carts = $total_value = $order_total = 0;
244
  $return_recovered_orders = array();
245
+ $per_page = $this->per_page;
246
+ $i = 0;
247
+ foreach ( $ac_carts_results as $key => $value ) {
248
+ $count_carts += 1;
249
+ $cart_detail = json_decode( $value->abandoned_cart_info );
250
+ $product_details = new stdClass();
251
+ if ( isset( $cart_detail->cart ) ) {
252
+ $product_details = $cart_detail->cart;
253
+ }
254
+ $line_total = 0;
255
+
256
+ if ( false != $product_details && is_object( $product_details ) && count( get_object_vars( $product_details ) ) > 0 ) {
257
+ foreach ( $product_details as $k => $v ) {
258
+ if ( $v->line_subtotal_tax != 0 && $v->line_subtotal_tax > 0 ) {
259
+ $line_total = $line_total + $v->line_total + $v->line_subtotal_tax;
260
+ } else {
261
+ $line_total = $line_total + $v->line_total;
262
+ }
263
+ }
264
+ }
265
+ $total_value += $line_total;
266
  }
267
+ // $total_value = wc_price( $total_value );
268
  $this->total_order_amount = $total_value;
269
  $this->total_abandoned_cart_count = $count_carts;
270
  $recovered_order_total = 0;
271
  $this->total_recover_amount = round( $recovered_order_total, $number_decimal );
272
  $this->recovered_item = 0;
273
+ $table_data = '';
274
+
275
  foreach ( $ac_results as $key => $value ) {
276
+ if ( $value->recovered_cart != 0 ) {
277
+ $return_recovered_orders[ $i ] = new stdClass();
278
+ $recovered_id = $value->recovered_cart;
279
+ $rec_order = get_post_meta( $recovered_id );
280
+ $woo_order = array();
281
+ try {
282
+ $woo_order = wc_get_order( $recovered_id );
283
+ if ( version_compare( $woocommerce->version, '3.0.0', '>=' ) ) {
284
+ $order = get_post( $recovered_id );
285
+ $recovered_date = strtotime( $order->post_date );
286
+ $recovered_date_format = date_i18n( get_option( 'date_format' ), $recovered_date );
287
+ $recovered_time_format = date_i18n( get_option( 'time_format' ), $recovered_date );
288
+ $recovered_date_new = $recovered_date_format . ' ' . $recovered_time_format;
289
+ } else {
290
+ $recovered_date = strtotime( $woo_order->order_date );
291
  $recovered_date_format = date_i18n( get_option( 'date_format' ), $recovered_date );
292
+ $recovered_time_format = date_i18n( get_option( 'time_format' ), $recovered_date );
293
  $recovered_date_new = $recovered_date_format . ' ' . $recovered_time_format;
294
+ }
295
+ $recovered_item += 1;
296
+
297
+ if ( isset( $rec_order ) && $rec_order != false ) {
298
+ $recovered_total += $rec_order['_order_total'][0];
299
+ }
300
+ $date_format = date_i18n( get_option( 'date_format' ), $value->abandoned_cart_time );
301
+ $time_format = date_i18n( get_option( 'time_format' ), $value->abandoned_cart_time );
302
+ $abandoned_date = $date_format . ' ' . $time_format;
303
+ $abandoned_order_id = $value->id;
304
+ $billing_first_name = $billing_last_name = $billing_email = '';
305
+ $recovered_order_total = 0;
306
+
307
+ if ( isset( $rec_order['_billing_first_name'][0] ) ) {
308
+ $billing_first_name = $rec_order['_billing_first_name'][0];
309
+ }
310
+
311
+ if ( isset( $rec_order['_billing_last_name'][0] ) ) {
312
+ $billing_last_name = $rec_order['_billing_last_name'][0];
313
+ }
314
+
315
+ if ( isset( $rec_order['_billing_email'][0] ) ) {
316
+ $billing_email = $rec_order['_billing_email'][0];
317
+ }
318
+
319
+ if ( isset( $rec_order['_order_total'][0] ) ) {
320
+ $recovered_order_total = $rec_order['_order_total'][0];
321
+ }
322
+
323
+ $return_recovered_orders[ $i ]->user_name = $billing_first_name . ' ' . $billing_last_name;
324
+ $return_recovered_orders[ $i ]->user_email_id = $billing_email;
325
+ $return_recovered_orders[ $i ]->created_on = $abandoned_date;
326
+ $return_recovered_orders[ $i ]->recovered_date = $recovered_date_new;
327
+ $return_recovered_orders[ $i ]->recovered_id = $recovered_id;
328
+ $return_recovered_orders[ $i ]->recover_order_date = $recovered_date;
329
+ $return_recovered_orders[ $i ]->abandoned_date = $value->abandoned_cart_time;
330
+ $return_recovered_orders[ $i ]->order_total = wc_price( $recovered_order_total );
331
+
332
+ $this->recovered_item = $recovered_item;
333
+ $this->total_recover_amount = round( ( $recovered_order_total + $this->total_recover_amount ), $number_decimal );
334
+ $i++;
335
+ } catch ( Exception $e ) {
336
+
337
+ }
338
+ }
 
 
 
 
 
 
339
  }
340
+ $this->total_order_amount = wc_price( $this->total_order_amount + $this->total_recover_amount );
341
  $this->total_abandoned_cart_count = $this->total_abandoned_cart_count + $this->recovered_item;
342
+ $templates_count = count( $return_recovered_orders );
343
+ $this->total_count = $templates_count;
344
+ // sort for order date
345
+ if ( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'created_on' ) {
346
+ if ( isset( $_GET['order'] ) && $_GET['order'] == 'asc' ) {
347
+ usort( $return_recovered_orders, array( __CLASS__, 'wcal_class_recovered_created_on_asc' ) );
348
  } else {
349
+ usort( $return_recovered_orders, array( __CLASS__, 'wcal_class_recovered_created_on_dsc' ) );
350
  }
351
  }
352
  // sort for customer name
353
+ elseif ( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'recovered_date' ) {
354
+ if ( isset( $_GET['order'] ) && $_GET['order'] == 'asc' ) {
355
+ usort( $return_recovered_orders, array( __CLASS__, 'wcal_class_recovered_date_asc' ) );
356
  } else {
357
+ usort( $return_recovered_orders, array( __CLASS__, 'wcal_class_recovered_date_dsc' ) );
358
  }
359
  }
360
  // Pagination per page
361
+ if ( isset( $_GET['paged'] ) && $_GET['paged'] > 1 ) {
362
+ $page_number = $_GET['paged'] - 1;
363
+ $k = $per_page * $page_number;
364
  } else {
365
+ $k = 0;
366
  }
367
  $return_recovered_orders_display = array();
368
+ for ( $j = $k; $j < ( $k + $per_page ); $j++ ) {
369
+ if ( isset( $return_recovered_orders[ $j ] ) ) {
370
+ $return_recovered_orders_display[ $j ] = $return_recovered_orders[ $j ];
371
+ } else {
372
+ break;
373
+ }
374
+ }
375
+ return apply_filters( 'wcal_recovered_orders_table_data', $return_recovered_orders_display );
376
  }
377
+
378
  /**
379
  * It will sort the ascending data based on the abandoned cart date.
380
+ *
381
  * @param array | object $value1 All data of the list
382
  * @param array | object $value2 All data of the list
383
+ * @return timestamp
384
  * @since 2.5.2
385
  */
386
+ function wcal_class_recovered_created_on_asc( $value1, $value2 ) {
387
+ return $value1->abandoned_date - $value2->abandoned_date;
388
  }
389
+
390
  /**
391
  * It will sort the descending data based on the abandoned cart date.
392
+ *
393
  * @param array | object $value1 All data of the list
394
  * @param array | object $value2 All data of the list
395
+ * @return timestamp
396
  * @since 2.5.2
397
  */
398
+ function wcal_class_recovered_created_on_dsc( $value1, $value2 ) {
399
+ return $value2->abandoned_date - $value1->abandoned_date;
400
  }
401
 
402
  /**
403
  * It will sort the ascending data based on the recovered cart date.
404
+ *
405
  * @param array | object $value1 All data of the list
406
  * @param array | object $value2 All data of the list
407
  * @globals mixed $woocommerce
408
+ * @return timestamp
409
  * @since 2.5.2
410
+ */
411
+ function wcal_class_recovered_date_asc( $value1, $value2 ) {
412
 
413
  global $woocommerce;
414
+ if ( version_compare( $woocommerce->version, '3.0.0', '>=' ) ) {
415
+ $value1 = $value1->recover_order_date;
416
+ $value2 = $value2->recover_order_date;
417
+
418
  $value1->recover_order_date = $value1->getTimestamp();
419
  $value2->recover_order_date = $value2->getTimestamp();
420
  }
421
+ return $value1->recover_order_date - $value2->recover_order_date;
422
  }
423
 
424
  /**
425
  * It will sort the descending data based on the recovered cart date.
426
+ *
427
  * @param array | object $value1 All data of the list
428
  * @param array | object $value2 All data of the list
429
  * @globals mixed $woocommerce
430
+ * @return timestamp
431
  * @since 2.5.2
432
  */
433
+
434
+ function wcal_class_recovered_date_dsc( $value1, $value2 ) {
435
  global $woocommerce;
436
+ if ( version_compare( $woocommerce->version, '3.0.0', '>=' ) ) {
437
+ $value1 = $value1->recover_order_date;
438
+ $value2 = $value2->recover_order_date;
439
+
440
  $value1->recover_order_date = $value1->getTimestamp();
441
  $value2->recover_order_date = $value2->getTimestamp();
442
  }
443
+ return $value2->recover_order_date - $value1->recover_order_date;
444
  }
445
+
446
  /**
447
  * It will display the data for the recovered column.
448
+ *
449
  * @param array | object $wcal_abandoned_orders All data of the list
450
+ * @param stirng $column_name Name of the column
451
  * @return string $value Data of the column
452
  * @since 2.5.2
453
  */
454
  public function column_default( $wcal_abandoned_orders, $column_name ) {
455
+ $value = '';
456
+ switch ( $column_name ) {
457
+ case 'user_email_id':
458
+ if ( isset( $wcal_abandoned_orders->user_email_id ) ) {
459
+
460
+ $user_email_id = "<a href= mailto:$wcal_abandoned_orders->user_email_id>" . $wcal_abandoned_orders->user_email_id . '</a>';
461
+ $value = $user_email_id;
462
+ }
463
+ break;
464
+ case 'created_on':
465
+ if ( isset( $wcal_abandoned_orders->created_on ) ) {
466
+ $value = $wcal_abandoned_orders->created_on;
467
+ }
468
  break;
469
+ case 'recovered_date':
470
+ if ( isset( $wcal_abandoned_orders->recovered_date ) ) {
471
+ $value = $wcal_abandoned_orders->recovered_date;
472
+ }
473
  break;
474
+ case 'order_total':
475
+ if ( isset( $wcal_abandoned_orders->order_total ) ) {
476
+ $value = $wcal_abandoned_orders->order_total;
477
+ }
478
  break;
479
+ default:
 
 
 
 
 
480
  $value = isset( $wcal_abandoned_orders->$column_name ) ? $wcal_abandoned_orders->$column_name : '';
481
  break;
482
+ }
483
  return apply_filters( 'wcal_recovered_orders_column_default', $value, $wcal_abandoned_orders, $column_name );
484
  }
485
  }
486
+
includes/classes/class-wcal-templates-table.php CHANGED
@@ -40,7 +40,7 @@ class WCAL_Templates_Table extends WP_List_Table {
40
  */
41
  public $total_count;
42
 
43
- /**
44
  * It will add the bulk action function and other variable needed for the class.
45
  *
46
  * @see WP_List_Table::__construct()
@@ -49,17 +49,20 @@ class WCAL_Templates_Table extends WP_List_Table {
49
  public function __construct() {
50
  global $status, $page;
51
  // Set parent defaults
52
- parent::__construct( array(
53
- 'singular' => __( 'template_id', 'woocommerce-abandoned-cart' ), //singular name of the listed records
54
- 'plural' => __( 'template_ids', 'woocommerce-abandoned-cart' ), //plural name of the listed records
55
- 'ajax' => false // Does this table support ajax?
56
- ) );
 
 
57
  $this->process_bulk_action();
58
- $this->base_url = admin_url( 'admin.php?page=woocommerce_ac_page&action=emailtemplates' );
59
  }
60
 
61
  /**
62
  * It will prepare the list of the templates, like columns, pagination, sortable column, all data.
 
63
  * @since 2.5.2
64
  */
65
  public function wcal_templates_prepare_items() {
@@ -72,56 +75,60 @@ class WCAL_Templates_Table extends WP_List_Table {
72
  $total_items = $this->total_count;
73
  $this->items = $data;
74
 
75
- $this->set_pagination_args( array(
76
- 'total_items' => $total_items, // WE have to calculate the total number of items
77
- 'per_page' => $this->per_page, // WE have to determine how many items to show on a page
78
- 'total_pages' => ceil( $total_items / $this->per_page ) // WE have to calculate the total number of pages
79
- )
 
80
  );
81
  }
82
 
83
  /**
84
  * It will add the columns templates list.
 
85
  * @return array $columns All columns name.
86
  * @since 2.5.2
87
  */
88
  public function get_columns() {
89
- $columns = array(
90
- 'cb' => '<input type="checkbox" />',
91
- 'sr' => __( 'Sr', 'woocommerce-abandoned-cart' ),
92
- 'template_name' => __( 'Name Of Template', 'woocommerce-abandoned-cart' ),
93
- 'sent_time' => __( 'Sent After Set Time', 'woocommerce-abandoned-cart' ),
94
- 'activate' => __( 'Active ?', 'woocommerce-abandoned-cart' )
95
  );
96
- return apply_filters( 'wcal_templates_columns', $columns );
97
  }
98
  /**
99
  * It is used to add the check box for the items.
 
100
  * @param string $item
101
  * @return string
102
  * @since 2.5.2
103
  */
104
  function column_cb( $item ) {
105
- $template_id = '';
106
- if( isset( $item->id ) && "" != $item->id ) {
107
- $template_id = $item->id;
108
- }
109
- return sprintf(
110
- '<input type="checkbox" name="%1$s[]" value="%2$s" />',
111
- 'template_id',
112
- $template_id
113
- );
114
  }
115
 
116
  /**
117
  * We can mention on which column we need the sorting. Here we have template name, email sent time
 
118
  * @return array $columns Name of the column
119
  * @since 2.5.2
120
  */
121
  public function templates_get_sortable_columns() {
122
  $columns = array(
123
- 'template_name' => array( 'template_name', false ),
124
- 'sent_time' => array( 'sent_time',false),
125
  );
126
  return apply_filters( 'wcal_templates_sortable_columns', $columns );
127
  }
@@ -129,208 +136,234 @@ class WCAL_Templates_Table extends WP_List_Table {
129
  /**
130
  * It will add the hover link on the template name.
131
  * This function used for individual delete, edit of row.
 
132
  * @since 2.5.2
133
  * @param array $template_row_info Contains all the data of the template row
134
  * @return string $value All hover links, here we have edit and delete
135
- *
136
  */
137
  public function column_template_name( $template_row_info ) {
138
- $row_actions = array();
139
- $value = '';
140
- $template_id = 0;
141
- if( isset( $template_row_info->template_name ) ) {
142
- $template_id = $template_row_info->id ;
143
 
144
- $row_actions['edit'] = '<a href="' . wp_nonce_url( add_query_arg( array( 'action' => 'emailtemplates', 'mode'=>'edittemplate', 'id' => $template_row_info->id ), $this->base_url ), 'abandoned_order_nonce') . '">' . __( 'Edit', 'woocommerce-abandoned-cart' ) . '</a>';
145
- $row_actions['delete'] = '<a href="' . wp_nonce_url( add_query_arg( array( 'action' => 'wcal_delete_template', 'template_id' => $template_row_info->id ), $this->base_url ), 'abandoned_order_nonce') . '">' . __( 'Delete', 'woocommerce-abandoned-cart' ) . '</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
- $email = $template_row_info->template_name;
148
- $value = $email . $this->row_actions( $row_actions );
149
- }
150
- return apply_filters( 'wcal_template_single_column', $value, $template_id, 'email' );
151
  }
152
 
153
- /**
154
- * It will generate the templates list data.
155
- * @globals mixed $wpdb
156
- * @return array $return_templates_data_display Key and value of all the columns
157
- * @since 2.5.2
158
- */
 
159
  public function wcal_templates_data() {
160
  global $wpdb;
161
  $return_templates_data = array();
162
  $per_page = $this->per_page;
163
  $results = array();
164
- $query = "SELECT wpet . * FROM `" . $wpdb->prefix . "ac_email_templates_lite` AS wpet ORDER BY day_or_hour desc , frequency asc";
165
- $results = $wpdb->get_results( $query );
166
- $i = 0;
167
 
168
  foreach ( $results as $key => $value ) {
169
- $return_templates_data[$i] = new stdClass();
170
- $id = $value->id;
171
- $query_no_emails = "SELECT * FROM " . $wpdb->prefix . "ac_sent_history_lite WHERE template_id= %d";
172
- $subject = $value->subject;
173
- $body = $value->body;
174
- $is_active = $value->is_active;
175
 
176
- if ( $is_active == '1' ) {
177
- $active = "Deactivate";
178
- } else {
179
- $active = "Activate";
180
- }
181
- $frequency = $value->frequency;
182
- $day_or_hour = $value->day_or_hour;
183
- $return_templates_data[ $i ]->sr = $i+1;
184
- $return_templates_data[ $i ]->id = $id;
185
- $return_templates_data[ $i ]->template_name = $value->template_name;
186
- $return_templates_data[ $i ]->sent_time = __( $frequency . " " . $day_or_hour . "After Abandonment", 'woocommerce-abandoned-cart' );
187
- $return_templates_data[ $i ]->activate = $active;
188
- $return_templates_data[ $i ]->is_active = $is_active;
189
- $i++;
190
- }
191
- $templates_count = count( $return_templates_data );
192
- $this->total_count = $templates_count;
193
- // sort for order date
194
- if( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'template_name' ) {
195
- if( isset($_GET['order'] ) && $_GET['order'] == 'asc' ) {
196
- usort( $return_templates_data, array( __CLASS__ , "wcal_class_template_name_asc" ) );
197
  } else {
198
- usort( $return_templates_data, array( __CLASS__ , "wcal_class_template_name_dsc") );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  }
200
  }
201
  // sort for customer name
202
- else if ( isset( $_GET['orderby']) && $_GET['orderby'] == 'sent_time' ) {
203
- if ( isset( $_GET['order'] ) && $_GET['order'] == 'asc' ) {
204
- usort( $return_templates_data, array( __CLASS__ , "wcal_class_sent_time_asc" ) );
205
  } else {
206
- usort( $return_templates_data, array( __CLASS__ , "wcal_class_sent_time_dsc" ) );
207
  }
208
  }
209
  // Pagination per page
210
- if( isset( $_GET['paged'] ) && $_GET['paged'] > 1 ) {
211
- $page_number = $_GET['paged'] - 1;
212
- $k = $per_page * $page_number;
213
  } else {
214
- $k = 0;
215
  }
216
  $return_templates_data_display = array();
217
- for( $j = $k; $j < ( $k+$per_page ); $j++ ) {
218
- if( isset( $return_templates_data[$j] ) ) {
219
- $return_templates_data_display[$j] = $return_templates_data[$j];
220
- } else {
221
- break;
222
- }
223
  }
224
 
225
- return apply_filters( 'wcal_templates_table_data', $return_templates_data_display );
226
  }
227
 
228
  /**
229
  * It will sort the data alphabetally ascending on the template name.
 
230
  * @param array | object $value1 All data of the list
231
  * @param array | object $value2 All data of the list
232
  * @return sorted array
233
  * @since 2.5.2
234
  */
235
- function wcal_class_template_name_asc( $value1,$value2 ) {
236
- return strcasecmp( $value1->template_name,$value2->template_name );
237
  }
238
 
239
  /**
240
  * It will sort the data alphabetally descending on the template name.
 
241
  * @param array | object $value1 All data of the list
242
  * @param array | object $value2 All data of the list
243
  * @return sorted array
244
  * @since 2.5.2
245
  */
246
- function wcal_class_template_name_dsc( $value1,$value2 ) {
247
- return strcasecmp( $value2->template_name,$value1->template_name );
248
  }
249
 
250
  /**
251
  * It will sort the data alphanumeric ascending on the template time.
 
252
  * @param array | object $value1 All data of the list
253
  * @param array | object $value2 All data of the list
254
  * @return sorted array
255
  * @since 2.5.2
256
  */
257
- function wcal_class_sent_time_asc( $value1,$value2 ) {
258
- return strnatcasecmp( $value1->sent_time,$value2->sent_time );
259
  }
260
 
261
  /**
262
  * It will sort the data alphanumeric descending on the template time.
 
263
  * @param array | object $value1 All data of the list
264
  * @param array | object $value2 All data of the list
265
  * @return sorted array
266
  * @since 2.5.2
267
  */
268
- function wcal_class_sent_time_dsc( $value1,$value2 ) {
269
- return strnatcasecmp( $value2->sent_time,$value1->sent_time );
270
  }
271
 
272
  /**
273
  * It will display the data for the templates list
 
274
  * @param array | object $wcal_abandoned_orders All data of the list
275
- * @param stirng $column_name Name of the column
276
  * @return string $value Data of the column
277
  * @since 2.5.2
278
  */
279
  public function column_default( $wcal_abandoned_orders, $column_name ) {
280
- $value = '';
281
- switch ( $column_name ) {
282
- case 'sr' :
283
- if( isset( $wcal_abandoned_orders->sr ) ) {
284
- $value = $wcal_abandoned_orders->sr;
285
- }
286
- break;
287
- case 'template_name' :
288
- if( isset( $wcal_abandoned_orders->template_name ) ) {
289
- $value = $wcal_abandoned_orders->template_name;
290
- }
291
  break;
292
- case 'sent_time' :
293
- if( isset( $wcal_abandoned_orders->sent_time ) ) {
294
- $value = $wcal_abandoned_orders->sent_time;
295
- }
296
  break;
297
- case 'activate' :
298
- if( isset( $wcal_abandoned_orders->activate ) ) {
299
- $active = $wcal_abandoned_orders->activate;
300
- $id = $wcal_abandoned_orders->id;
301
- $is_active = $wcal_abandoned_orders->is_active;
302
- $active = '';
303
- $active_text = '';
304
- if ( $is_active == '1' ) {
305
- $active = "on";
306
- $active_text = __( "on", 'woocommerce-abandoned-cart' );
307
- } else {
308
- $active = "off";
309
- $active_text = __( "off", 'woocommerce-abandoned-cart' );
310
- }
311
- //$value = '<a href="#" onclick="wcal_activate_email_template('. $id.', '.$is_active.' )"> '.$active_text.'</a>';
312
- $value = '<button type="button" class="wcal-switch wcal-toggle-template-status" '
313
- . 'wcal-template-id="'. $id .'" '
314
- . 'wcal-template-switch="'. ( $active ) . '">'
315
  . $active_text . '</button>';
316
- }
317
  break;
318
- default:
319
  $value = isset( $wcal_abandoned_orders->$column_name ) ? $wcal_abandoned_orders->$column_name : '';
320
  break;
321
- }
322
- return apply_filters( 'wcal_template_column_default', $value, $wcal_abandoned_orders, $column_name );
323
  }
324
 
325
  /**
326
  * It will add the bulk action, here Delete
 
327
  * @return array
328
  * @since 2.5.2
329
  */
330
  public function get_bulk_actions() {
331
- return array(
332
- 'wcal_delete_template' => __( 'Delete', 'woocommerce-abandoned-cart' )
333
- );
334
  }
335
  }
336
- ?>
40
  */
41
  public $total_count;
42
 
43
+ /**
44
  * It will add the bulk action function and other variable needed for the class.
45
  *
46
  * @see WP_List_Table::__construct()
49
  public function __construct() {
50
  global $status, $page;
51
  // Set parent defaults
52
+ parent::__construct(
53
+ array(
54
+ 'singular' => __( 'template_id', 'woocommerce-abandoned-cart' ), // singular name of the listed records
55
+ 'plural' => __( 'template_ids', 'woocommerce-abandoned-cart' ), // plural name of the listed records
56
+ 'ajax' => false, // Does this table support ajax?
57
+ )
58
+ );
59
  $this->process_bulk_action();
60
+ $this->base_url = admin_url( 'admin.php?page=woocommerce_ac_page&action=emailtemplates' );
61
  }
62
 
63
  /**
64
  * It will prepare the list of the templates, like columns, pagination, sortable column, all data.
65
+ *
66
  * @since 2.5.2
67
  */
68
  public function wcal_templates_prepare_items() {
75
  $total_items = $this->total_count;
76
  $this->items = $data;
77
 
78
+ $this->set_pagination_args(
79
+ array(
80
+ 'total_items' => $total_items, // WE have to calculate the total number of items
81
+ 'per_page' => $this->per_page, // WE have to determine how many items to show on a page
82
+ 'total_pages' => ceil( $total_items / $this->per_page ), // WE have to calculate the total number of pages
83
+ )
84
  );
85
  }
86
 
87
  /**
88
  * It will add the columns templates list.
89
+ *
90
  * @return array $columns All columns name.
91
  * @since 2.5.2
92
  */
93
  public function get_columns() {
94
+ $columns = array(
95
+ 'cb' => '<input type="checkbox" />',
96
+ 'sr' => __( 'Sr', 'woocommerce-abandoned-cart' ),
97
+ 'template_name' => __( 'Name Of Template', 'woocommerce-abandoned-cart' ),
98
+ 'sent_time' => __( 'Sent After Set Time', 'woocommerce-abandoned-cart' ),
99
+ 'activate' => __( 'Active ?', 'woocommerce-abandoned-cart' ),
100
  );
101
+ return apply_filters( 'wcal_templates_columns', $columns );
102
  }
103
  /**
104
  * It is used to add the check box for the items.
105
+ *
106
  * @param string $item
107
  * @return string
108
  * @since 2.5.2
109
  */
110
  function column_cb( $item ) {
111
+ $template_id = '';
112
+ if ( isset( $item->id ) && '' != $item->id ) {
113
+ $template_id = $item->id;
114
+ }
115
+ return sprintf(
116
+ '<input type="checkbox" name="%1$s[]" value="%2$s" />',
117
+ 'template_id',
118
+ $template_id
119
+ );
120
  }
121
 
122
  /**
123
  * We can mention on which column we need the sorting. Here we have template name, email sent time
124
+ *
125
  * @return array $columns Name of the column
126
  * @since 2.5.2
127
  */
128
  public function templates_get_sortable_columns() {
129
  $columns = array(
130
+ 'template_name' => array( 'template_name', false ),
131
+ 'sent_time' => array( 'sent_time', false ),
132
  );
133
  return apply_filters( 'wcal_templates_sortable_columns', $columns );
134
  }
136
  /**
137
  * It will add the hover link on the template name.
138
  * This function used for individual delete, edit of row.
139
+ *
140
  * @since 2.5.2
141
  * @param array $template_row_info Contains all the data of the template row
142
  * @return string $value All hover links, here we have edit and delete
 
143
  */
144
  public function column_template_name( $template_row_info ) {
145
+ $row_actions = array();
146
+ $value = '';
147
+ $template_id = 0;
148
+ if ( isset( $template_row_info->template_name ) ) {
149
+ $template_id = $template_row_info->id;
150
 
151
+ $row_actions['edit'] = '<a href="' . wp_nonce_url(
152
+ add_query_arg(
153
+ array(
154
+ 'action' => 'emailtemplates',
155
+ 'mode' => 'edittemplate',
156
+ 'id' => $template_row_info->id,
157
+ ),
158
+ $this->base_url
159
+ ),
160
+ 'abandoned_order_nonce'
161
+ ) . '">' . __( 'Edit', 'woocommerce-abandoned-cart' ) . '</a>';
162
+ $row_actions['delete'] = '<a href="' . wp_nonce_url(
163
+ add_query_arg(
164
+ array(
165
+ 'action' => 'wcal_delete_template',
166
+ 'template_id' => $template_row_info->id,
167
+ ),
168
+ $this->base_url
169
+ ),
170
+ 'abandoned_order_nonce'
171
+ ) . '">' . __( 'Delete', 'woocommerce-abandoned-cart' ) . '</a>';
172
 
173
+ $email = $template_row_info->template_name;
174
+ $value = $email . $this->row_actions( $row_actions );
175
+ }
176
+ return apply_filters( 'wcal_template_single_column', $value, $template_id, 'email' );
177
  }
178
 
179
+ /**
180
+ * It will generate the templates list data.
181
+ *
182
+ * @globals mixed $wpdb
183
+ * @return array $return_templates_data_display Key and value of all the columns
184
+ * @since 2.5.2
185
+ */
186
  public function wcal_templates_data() {
187
  global $wpdb;
188
  $return_templates_data = array();
189
  $per_page = $this->per_page;
190
  $results = array();
191
+ $query = 'SELECT wpet . * FROM `' . $wpdb->prefix . 'ac_email_templates_lite` AS wpet ORDER BY day_or_hour desc , frequency asc';
192
+ $results = $wpdb->get_results( $query );
193
+ $i = 0;
194
 
195
  foreach ( $results as $key => $value ) {
196
+ $return_templates_data[ $i ] = new stdClass();
197
+ $id = $value->id;
198
+ $query_no_emails = 'SELECT * FROM ' . $wpdb->prefix . 'ac_sent_history_lite WHERE template_id= %d';
199
+ $subject = $value->subject;
200
+ $body = $value->body;
201
+ $is_active = $value->is_active;
202
 
203
+ if ( $is_active == '1' ) {
204
+ $active = 'Deactivate';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  } else {
206
+ $active = 'Activate';
207
+ }
208
+ $frequency = $value->frequency;
209
+ $day_or_hour = $value->day_or_hour;
210
+ $return_templates_data[ $i ]->sr = $i + 1;
211
+ $return_templates_data[ $i ]->id = $id;
212
+ $return_templates_data[ $i ]->template_name = $value->template_name;
213
+ $return_templates_data[ $i ]->sent_time = __( $frequency . ' ' . $day_or_hour . 'After Abandonment', 'woocommerce-abandoned-cart' );
214
+ $return_templates_data[ $i ]->activate = $active;
215
+ $return_templates_data[ $i ]->is_active = $is_active;
216
+ $i++;
217
+ }
218
+ $templates_count = count( $return_templates_data );
219
+ $this->total_count = $templates_count;
220
+ // sort for order date
221
+ if ( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'template_name' ) {
222
+ if ( isset( $_GET['order'] ) && $_GET['order'] == 'asc' ) {
223
+ usort( $return_templates_data, array( __CLASS__, 'wcal_class_template_name_asc' ) );
224
+ } else {
225
+ usort( $return_templates_data, array( __CLASS__, 'wcal_class_template_name_dsc' ) );
226
  }
227
  }
228
  // sort for customer name
229
+ elseif ( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'sent_time' ) {
230
+ if ( isset( $_GET['order'] ) && $_GET['order'] == 'asc' ) {
231
+ usort( $return_templates_data, array( __CLASS__, 'wcal_class_sent_time_asc' ) );
232
  } else {
233
+ usort( $return_templates_data, array( __CLASS__, 'wcal_class_sent_time_dsc' ) );
234
  }
235
  }
236
  // Pagination per page
237
+ if ( isset( $_GET['paged'] ) && $_GET['paged'] > 1 ) {
238
+ $page_number = $_GET['paged'] - 1;
239
+ $k = $per_page * $page_number;
240
  } else {
241
+ $k = 0;
242
  }
243
  $return_templates_data_display = array();
244
+ for ( $j = $k; $j < ( $k + $per_page ); $j++ ) {
245
+ if ( isset( $return_templates_data[ $j ] ) ) {
246
+ $return_templates_data_display[ $j ] = $return_templates_data[ $j ];
247
+ } else {
248
+ break;
249
+ }
250
  }
251
 
252
+ return apply_filters( 'wcal_templates_table_data', $return_templates_data_display );
253
  }
254
 
255
  /**
256
  * It will sort the data alphabetally ascending on the template name.
257
+ *
258
  * @param array | object $value1 All data of the list
259
  * @param array | object $value2 All data of the list
260
  * @return sorted array
261
  * @since 2.5.2
262
  */
263
+ function wcal_class_template_name_asc( $value1, $value2 ) {
264
+ return strcasecmp( $value1->template_name, $value2->template_name );
265
  }
266
 
267
  /**
268
  * It will sort the data alphabetally descending on the template name.
269
+ *
270
  * @param array | object $value1 All data of the list
271
  * @param array | object $value2 All data of the list
272
  * @return sorted array
273
  * @since 2.5.2
274
  */
275
+ function wcal_class_template_name_dsc( $value1, $value2 ) {
276
+ return strcasecmp( $value2->template_name, $value1->template_name );
277
  }
278
 
279
  /**
280
  * It will sort the data alphanumeric ascending on the template time.
281
+ *
282
  * @param array | object $value1 All data of the list
283
  * @param array | object $value2 All data of the list
284
  * @return sorted array
285
  * @since 2.5.2
286
  */
287
+ function wcal_class_sent_time_asc( $value1, $value2 ) {
288
+ return strnatcasecmp( $value1->sent_time, $value2->sent_time );
289
  }
290
 
291
  /**
292
  * It will sort the data alphanumeric descending on the template time.
293
+ *
294
  * @param array | object $value1 All data of the list
295
  * @param array | object $value2 All data of the list
296
  * @return sorted array
297
  * @since 2.5.2
298
  */
299
+ function wcal_class_sent_time_dsc( $value1, $value2 ) {
300
+ return strnatcasecmp( $value2->sent_time, $value1->sent_time );
301
  }
302
 
303
  /**
304
  * It will display the data for the templates list
305
+ *
306
  * @param array | object $wcal_abandoned_orders All data of the list
307
+ * @param stirng $column_name Name of the column
308
  * @return string $value Data of the column
309
  * @since 2.5.2
310
  */
311
  public function column_default( $wcal_abandoned_orders, $column_name ) {
312
+ $value = '';
313
+ switch ( $column_name ) {
314
+ case 'sr':
315
+ if ( isset( $wcal_abandoned_orders->sr ) ) {
316
+ $value = $wcal_abandoned_orders->sr;
317
+ }
318
+ break;
319
+ case 'template_name':
320
+ if ( isset( $wcal_abandoned_orders->template_name ) ) {
321
+ $value = $wcal_abandoned_orders->template_name;
322
+ }
323
  break;
324
+ case 'sent_time':
325
+ if ( isset( $wcal_abandoned_orders->sent_time ) ) {
326
+ $value = $wcal_abandoned_orders->sent_time;
327
+ }
328
  break;
329
+ case 'activate':
330
+ if ( isset( $wcal_abandoned_orders->activate ) ) {
331
+ $active = $wcal_abandoned_orders->activate;
332
+ $id = $wcal_abandoned_orders->id;
333
+ $is_active = $wcal_abandoned_orders->is_active;
334
+ $active = '';
335
+ $active_text = '';
336
+ if ( $is_active == '1' ) {
337
+ $active = 'on';
338
+ $active_text = __( 'on', 'woocommerce-abandoned-cart' );
339
+ } else {
340
+ $active = 'off';
341
+ $active_text = __( 'off', 'woocommerce-abandoned-cart' );
342
+ }
343
+ // $value = '<a href="#" onclick="wcal_activate_email_template('. $id.', '.$is_active.' )"> '.$active_text.'</a>';
344
+ $value = '<button type="button" class="wcal-switch wcal-toggle-template-status" '
345
+ . 'wcal-template-id="' . $id . '" '
346
+ . 'wcal-template-switch="' . ( $active ) . '">'
347
  . $active_text . '</button>';
348
+ }
349
  break;
350
+ default:
351
  $value = isset( $wcal_abandoned_orders->$column_name ) ? $wcal_abandoned_orders->$column_name : '';
352
  break;
353
+ }
354
+ return apply_filters( 'wcal_template_column_default', $value, $wcal_abandoned_orders, $column_name );
355
  }
356
 
357
  /**
358
  * It will add the bulk action, here Delete
359
+ *
360
  * @return array
361
  * @since 2.5.2
362
  */
363
  public function get_bulk_actions() {
364
+ return array(
365
+ 'wcal_delete_template' => __( 'Delete', 'woocommerce-abandoned-cart' ),
366
+ );
367
  }
368
  }
369
+
includes/component/welcome-page/templates/welcome/welcome-page.php CHANGED
@@ -54,10 +54,6 @@
54
  <p><?php _e( 'The Abandoned Cart Pro plugin gives you features where you are able to recover more sales compared to the Lite plugin. Here are some notable features the Pro version provides.' ); ?></p>
55
 
56
  <div class="feature-section clearfix introduction">
57
- <div class="video feature-section-item" style="float:left;padding-right:10px;">
58
- <img src="https://www.tychesoftwares.com/wp-content/uploads/2017/08/atc_frontend.png"
59
- alt="<?php esc_attr_e( 'WooCommerce Abandoned Cart Lite', 'woocommerce-abandoned-cart' ); ?>" style="width:500px;">
60
- </div>
61
 
62
  <div class="content feature-section-item last-feature">
63
  <h3><?php esc_html_e( 'Capture Visitor Emails on click of Add to Cart button', 'woocommerce-abandoned-cart' ); ?></h3>
54
  <p><?php _e( 'The Abandoned Cart Pro plugin gives you features where you are able to recover more sales compared to the Lite plugin. Here are some notable features the Pro version provides.' ); ?></p>
55
 
56
  <div class="feature-section clearfix introduction">
 
 
 
 
57
 
58
  <div class="content feature-section-item last-feature">
59
  <h3><?php esc_html_e( 'Capture Visitor Emails on click of Add to Cart button', 'woocommerce-abandoned-cart' ); ?></h3>
includes/component/welcome-page/ts-welcome.php CHANGED
@@ -194,7 +194,7 @@ class Wcal_TS_Welcome {
194
  $ts_file_path = plugin_dir_url( __FILE__ ) ;
195
  // Badge for welcome page
196
  $badge_url = $ts_file_path . '/assets/images/icon-256x256.png';
197
-
198
  ob_start();
199
  wc_get_template( 'welcome/welcome-page.php', array(
200
  'plugin_name' => self::$plugin_name,
@@ -206,7 +206,7 @@ class Wcal_TS_Welcome {
206
  'get_welcome_header' => $this->get_welcome_header()
207
  ), self::$plugin_folder, self::$template_base );
208
  echo ob_get_clean();
209
-
210
  add_option( self::$plugin_prefix . '_pro_welcome_page_shown', 'yes' );
211
  add_option( self::$plugin_prefix . '_pro_welcome_page_shown_time', current_time( 'timestamp' ) );
212
  }
194
  $ts_file_path = plugin_dir_url( __FILE__ ) ;
195
  // Badge for welcome page
196
  $badge_url = $ts_file_path . '/assets/images/icon-256x256.png';
197
+ /*
198
  ob_start();
199
  wc_get_template( 'welcome/welcome-page.php', array(
200
  'plugin_name' => self::$plugin_name,
206
  'get_welcome_header' => $this->get_welcome_header()
207
  ), self::$plugin_folder, self::$template_base );
208
  echo ob_get_clean();
209
+ */
210
  add_option( self::$plugin_prefix . '_pro_welcome_page_shown', 'yes' );
211
  add_option( self::$plugin_prefix . '_pro_welcome_page_shown_time', current_time( 'timestamp' ) );
212
  }
includes/frontend/wcal_checkout_process.php CHANGED
@@ -1,35 +1,38 @@
1
  <?php
2
  /**
3
  * Checkout Process for Abandoned Cart Lite
4
- *
5
  * @since 5.3.0
6
  */
7
 
8
  // Exit if accessed directly
9
- if ( !defined( 'ABSPATH' ) ) exit;
 
 
10
 
11
- if ( !class_exists( 'Wcal_Checkout_Process' ) ) {
12
 
13
  /**
14
  * Process recovered orders
15
  */
16
  class Wcal_Checkout_Process {
17
-
18
  function __construct() {
19
-
20
- // delete added temp fields after order is placed
21
- add_filter ( 'woocommerce_order_details_after_order_table', array( &$this, 'wcal_action_after_delivery_session' ) );
22
 
23
- add_action( 'woocommerce_order_status_changed', array( &$this, 'wcal_update_cart_details' ), 10, 3);
24
- add_action( 'woocommerce_order_status_changed', array( &$this, 'wcal_send_recovery_email' ), 10, 3);
25
 
26
- add_action( 'woocommerce_checkout_order_processed', array( &$this, 'wcal_order_placed' ), 10 , 1 );
27
- add_filter( 'woocommerce_payment_complete_order_status', array( &$this, 'wcal_order_complete_action' ), 10 , 2 );
 
 
 
28
  }
29
 
30
  /**
31
- * When user places the order and reach the order recieved page, then it will check if it is abandoned cart and subsequently
32
  * recovered or not.
 
33
  * @hook woocommerce_order_details_after_order_table
34
  * @param array | object $order Order details
35
  * @globals mixed $wpdb
@@ -38,286 +41,289 @@ if ( !class_exists( 'Wcal_Checkout_Process' ) ) {
38
  */
39
  function wcal_action_after_delivery_session( $order ) {
40
 
41
- $order_id= $order->get_id();
42
-
43
- $wcal_get_order_status = $order->get_status();
44
-
45
- $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
46
- $get_sent_email_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', true );
47
-
48
- if ( isset( $get_sent_email_id_of_order ) && '' != $get_sent_email_id_of_order ) {
49
- /**
50
- * When Placed order button is clicked,
51
- * we create post meta for that order.
52
- * If that meta is found then update our plugin table for recovered cart
53
- */
54
- $this->wcal_updated_recovered_cart_table( $get_abandoned_id_of_order, $order_id, $get_sent_email_id_of_order, $order );
55
- } else if ( '' != $get_abandoned_id_of_order && isset( $get_abandoned_id_of_order ) ){
56
- /**
57
- * if order status is not pending or failed then
58
- * we will delete the abandoned cart record.
59
- * post meta will be created only if the cut off time has been reached.
60
- */
61
- $this->wcal_delete_abanadoned_data_on_order_status( $order_id , $get_abandoned_id_of_order, $wcal_get_order_status );
62
- }
63
-
64
- if ( wcal_common::wcal_get_cart_session( 'email_sent_id' ) != '' ) {
65
- wcal_common::wcal_unset_cart_session( 'email_sent_id' );
66
- }
67
  }
68
 
69
  /**
70
- * If customer had placed the order after cut off time and reached the order recived page then it will also delete the abandoned cart if the order status is not pending or failed.
71
- * @param int | string $order_id Order id
72
- * @param int | string $get_abandoned_id_of_order Abandoned cart id
73
- * @param string $wcal_get_order_status Order status
74
- * @globals mixed $wpdb
75
- * @globals mixed $woocommerce
76
- * @since 5.0
77
- */
78
- function wcal_delete_abanadoned_data_on_order_status( $order_id, $get_abandoned_id_of_order, $wcal_get_order_status ) {
79
-
80
- global $wpdb, $woocommerce;
81
-
82
- $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
 
83
  $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
84
  $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
85
 
86
- if ( 'pending' != $wcal_get_order_status || 'failed' != $wcal_get_order_status ) {
87
- if ( isset( $get_abandoned_id_of_order ) && '' != $get_abandoned_id_of_order ){
88
-
89
- $user_id_query = "SELECT user_id FROM `$wcal_history_table_name` WHERE id = %d";
90
- $user_id_results = $wpdb->get_results(
91
- $wpdb->prepare(
92
- $user_id_query,
93
- $get_abandoned_id_of_order
94
- )
95
- );
96
-
97
- if ( count( $user_id_results ) > 0 ){
98
- $wcal_user_id = $user_id_results[0]->user_id;
99
-
100
- if ( $wcal_user_id >= 63000000 ){
101
- $wpdb->delete( $wcal_guest_table_name, array( 'id' => $wcal_user_id ) );
102
- }
103
-
104
- $wpdb->delete( $wcal_history_table_name, array( 'id' => $get_abandoned_id_of_order ) );
105
- delete_post_meta( $order_id, 'wcal_recover_order_placed', $get_abandoned_id_of_order );
106
- }
107
- }
108
- }
109
- }
110
-
111
- /**
112
- * Updates the Abandoned Cart History table as well as the
113
- * Email Sent History table to indicate the order has been
114
- * recovered
115
- *
116
- * @param integer $cart_id - ID of the Abandoned Cart
117
- * @param integer $order_id - Recovered Order ID
118
- * @param integer $wcal_check_email_sent_to_cart - ID of the record in the Email Sent History table.
119
- * @param WC_Order $order - Order Details
120
- *
121
- * @since 7.7
122
- */
123
- function wcal_updated_recovered_cart_table( $cart_id, $order_id, $wcal_check_email_sent_to_cart, $order ) {
124
-
125
- global $wpdb;
126
-
127
- $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
128
  $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
129
  $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
130
 
131
- // check & make sure that the recovered cart details are not already updated
132
- $query_status = "SELECT recovered_cart FROM `$wcal_history_table_name` WHERE id = %d";
133
-
134
- $get_status = $wpdb->get_col(
135
- $wpdb->prepare(
136
- $query_status,
137
- $cart_id
138
- )
139
- );
140
-
141
- $recovered_status = isset( $get_status[0] ) ? $get_status[0] : '';
142
-
143
- if( $recovered_status == 0 ) {
144
-
145
- // Update the cart history table
146
- $update_details = array(
147
- 'recovered_cart' => $order_id,
148
- 'cart_ignored' => '1',
149
- );
150
-
151
- $current_user_id = get_current_user_id();
152
-
153
- if ( $current_user_id !== wcal_common::wcal_get_cart_session( 'user_id' ) &&
154
- $current_user_id != 0 ) {
155
- $update_details['user_id'] = $current_user_id;
156
- }
157
-
158
- // check if more than one reminder email has been sent
159
- $check_emails = "SELECT abandoned_order_id FROM `$wcal_sent_email_table_name` WHERE id = %d";
160
- $get_old_cart_id = $wpdb->get_col(
161
- $wpdb->prepare(
162
- $check_emails,
163
- $wcal_check_email_sent_to_cart
164
- )
165
- );
166
-
167
- $get_ids = array();
168
- if( isset( $get_old_cart_id ) ) {
169
- $query_ids = "SELECT id FROM `$wcal_sent_email_table_name` WHERE abandoned_order_id = %d";
170
- $get_ids = $wpdb->get_col( $wpdb->prepare( $query_ids, $get_old_cart_id ) );
171
- }
172
-
173
- $update_sent_history = array();
174
-
175
- if ( get_post_meta( $order_id, 'wcal_abandoned_timestamp', true ) != '' ) {
176
- $update_details['abandoned_cart_time'] = get_post_meta( $order_id, 'wcal_abandoned_timestamp', true );
177
-
178
- $update_sent_history['abandoned_order_id'] = $cart_id;
179
-
180
- delete_post_meta( $order_id, 'wcal_abandoned_timestamp', $update_details['abandoned_cart_time'] );
181
- }
182
-
183
- $wpdb->update( $wcal_history_table_name, $update_details, array( 'id' => $cart_id ) );
184
-
185
- // update the email sent history table
186
- if( is_array( $get_ids ) && count( $get_ids ) > 1 ) {
187
- $list_ids = implode( ',', $get_ids );
188
- $wpdb->query( "UPDATE `$wcal_sent_email_table_name` SET abandoned_order_id = $cart_id WHERE id IN ($list_ids)" );
189
- } else if ( isset( $update_sent_history['abandoned_order_id'] ) ) {
190
- $wpdb->update(
191
- $wcal_sent_email_table_name,
192
- $update_sent_history,
193
- array( 'id' => $wcal_check_email_sent_to_cart )
194
- );
195
- }
196
-
197
- // Add Order Note
198
- $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-abandoned-cart' ) );
199
- delete_post_meta( $order_id, 'wcal_abandoned_cart_id' );
200
- delete_post_meta( $order_id, 'wcal_recover_order_placed' );
201
- delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id' );
202
- delete_post_meta( $order_id, 'wcal_recovered_email_sent' );
203
- }
204
- }
205
 
206
  /**
207
  * Send email to admin when cart is recovered only via PayPal.
 
208
  * @hook woocommerce_order_status_changed
209
  * @param int | string $order_id Order id
210
- * @param string $wc_old_status Old status
211
- * @param string $wc_new_status New status
212
  * @globals mixed $wpdb
213
  * @globals mixed $woocommerce
214
  * @since 2.9
215
  */
216
  public function wcal_update_cart_details( $order_id, $wc_old_status, $wc_new_status ) {
217
 
218
- if( 'pending' != $wc_new_status &&
219
- 'failed' != $wc_new_status &&
220
- 'cancelled' != $wc_new_status &&
221
- 'trash' != $wc_new_status ) {
222
-
223
- global $wpdb;
224
 
225
- $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
226
  $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
227
  $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
228
 
229
- if( $order_id > 0 ) {
230
- $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
231
-
232
- if( $get_abandoned_id_of_order > 0 || wcal_common::wcal_get_cart_session( 'email_sent_id' ) != '' ) {
233
  // recovered order
234
- } else {
235
-
236
- $wcal_abandoned_id = get_post_meta( $order_id, 'wcal_abandoned_cart_id', true );
237
-
238
- // check if it's a guest cart
239
- $query_cart_data = "SELECT user_id, user_type FROM `$wcal_history_table_name` WHERE id = %d";
240
- $get_cart_data = $wpdb->get_results(
241
- $wpdb->prepare(
242
- $query_cart_data,
243
- $wcal_abandoned_id
244
- )
245
- );
246
-
247
- if( is_array( $get_cart_data ) && count( $get_cart_data ) > 0 ) {
248
- $user_type = $get_cart_data[0]->user_type;
249
- $user_id = $get_cart_data[0]->user_id;
250
-
251
- if( 'GUEST' == $user_type && $user_id >= 63000000 ) {
252
- $wpdb->delete( $wcal_guest_table_name, array( 'id' => $user_id ) );
253
- }
254
- }
255
- $wpdb->delete( $wcal_history_table_name, array( 'id' => $wcal_abandoned_id ) );
256
- }
257
- }
258
- }elseif ( 'pending' == $wc_old_status && 'cancelled' == $wc_new_status ) {
259
- global $wpdb;
260
-
261
- $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
262
- $wcal_abandoned_id = get_post_meta( $order_id, 'wcal_abandoned_cart_id', true );
263
 
264
  $wpdb->update( $wcal_history_table_name, array( 'cart_ignored' => '1' ), array( 'id' => $wcal_abandoned_id ) );
265
  }
266
  }
267
 
268
  /**
269
- * This function will send the email to the store admin when any abandoned cart email recovered.
270
- * @hook woocommerce_order_status_changed
271
- * @param int | string $order_id Order id
272
- * @param string $wcap_old_status Old status of the order
273
- * @param string $wcap_new_status New status of the order
274
- * @globals mixed $woocommerce
275
- * @since 1.0
276
- */
277
- function wcal_send_recovery_email( $order_id, $wcap_old_status, $wcap_new_status ) {
278
- global $woocommerce;
279
-
280
- if ( ( 'pending' == $wcap_old_status && 'processing' == $wcap_new_status )
281
- || ( 'pending' == $wcap_old_status && 'completed' == $wcap_new_status )
282
- || ( 'pending' == $wcap_old_status && 'on-hold' == $wcap_new_status )
283
- || ( 'failed' == $wcap_old_status && 'completed' == $wcap_new_status )
284
- || ( 'failed' == $wcap_old_status && 'processing' == $wcap_new_status )
285
- ) {
286
- $user_id = get_current_user_id();
287
- $ac_email_admin_recovery = get_option( 'ac_lite_email_admin_on_recovery' );
288
- $order = wc_get_order( $order_id );
289
- if( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
290
- $user_id = $order->get_user_id();
291
- } else {
292
- $user_id = $order->user_id;
293
- }
294
- if( $ac_email_admin_recovery == 'on' ) {
295
- $recovered_email_sent = get_post_meta( $order_id, 'wcal_recovered_email_sent', true );
296
- $wcal_check_order_is_recovered = $this->wcal_check_order_is_recovered ( $order_id );
297
-
298
- if ( 'yes' != $recovered_email_sent && true === $wcal_check_order_is_recovered ) { // indicates cart is abandoned
299
- $order = wc_get_order( $order_id );
300
- $email_heading = __( 'New Customer Order - Recovered', 'woocommerce' );
301
- $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
302
- $email_subject = __( 'New Customer Order - Recovered', 'woocommerce' );
303
- $user_email = get_option( 'admin_email' );
304
- $headers[] = "From: Admin <".$user_email.">";
305
- $headers[] = "Content-Type: text/html";
306
- // Buffer
307
- ob_start();
308
- // Get mail template
309
- wc_get_template(
310
- 'emails/admin-new-order.php',
311
- array(
 
312
  'order' => $order,
313
  'email_heading' => $email_heading,
314
- 'sent_to_admin' => false,
315
- 'plain_text' => false,
316
- 'email' => true
317
- )
318
- );
319
- // Get contents
320
- $email_body = ob_get_clean();
321
  wc_mail( $user_email, $email_subject, $email_body, $headers );
322
 
323
  update_post_meta( $order_id, 'wcal_recovered_email_sent', 'yes' );
@@ -328,6 +334,7 @@ if ( !class_exists( 'Wcal_Checkout_Process' ) ) {
328
 
329
  /**
330
  * For sending Recovery Email to Admin, we will check that order is recovered or not.
 
331
  * @param int | string $wcal_order_id Order id
332
  * @return boolean true | false
333
  * @globals mixed $wpdb
@@ -335,7 +342,7 @@ if ( !class_exists( 'Wcal_Checkout_Process' ) ) {
335
  */
336
  function wcal_check_order_is_recovered( $wcal_order_id ) {
337
  global $wpdb;
338
- $wcal_recover_order_query = "SELECT recovered_cart FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE recovered_cart = %d";
339
  $wcal_recover_order_query_result = $wpdb->get_results( $wpdb->prepare( $wcal_recover_order_query, $wcal_order_id ) );
340
  if ( count( $wcal_recover_order_query_result ) > 0 ) {
341
  return true;
@@ -344,11 +351,12 @@ if ( !class_exists( 'Wcal_Checkout_Process' ) ) {
344
  }
345
 
346
  /**
347
- * It will check the WooCommerce order status. If the order status is pending or failed the we will keep that cart record
348
  * as an abandoned cart.
349
  * It will be executed after order placed.
 
350
  * @hook woocommerce_payment_complete_order_status
351
- * @param string $order_status Order Status
352
  * @param int | string $order_id Order Id
353
  * @return string $order_status
354
  * @globals mixed $wpdb
@@ -363,34 +371,34 @@ if ( !class_exists( 'Wcal_Checkout_Process' ) ) {
363
  $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
364
  $get_sent_email_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', true );
365
 
366
- // Order Status passed in the function is either
367
- // 'processing' or 'complete' and may or may not reflect the actual order status.
368
- // Hence, always use the status fetched from the order object.
369
 
370
- $order_status = ( $order ) ? $order->get_status() : '';
371
 
372
- $wcal_ac_table_name = $wpdb->prefix . "ac_abandoned_cart_history_lite";
373
- $wcal_email_sent_history_table_name = $wpdb->prefix . "ac_sent_history_lite";
374
- $wcal_guest_ac_table_name = $wpdb->prefix . "ac_guest_abandoned_cart_history_lite";
375
 
376
- if ( 'pending' != $order_status && 'failed' != $order_status && 'cancelled' != $order_status && 'trash' != $order_status) {
377
- global $wpdb;
378
 
379
- if ( isset( $get_abandoned_id_of_order ) && '' != $get_abandoned_id_of_order ){
380
 
381
- $ac_user_id_query = "SELECT user_id, abandoned_cart_time FROM `$wcal_ac_table_name` WHERE id = %d";
382
- $ac_user_id_result = $wpdb->get_results(
383
- $wpdb->prepare(
384
- $ac_user_id_query,
385
- $get_abandoned_id_of_order
386
- )
387
- );
388
 
389
- if ( count( $ac_user_id_result ) > 0 ){
390
  $wcal_user_id = $ac_user_id_result[0]->user_id;
391
 
392
- if ( $wcal_user_id >= 63000000 ){
393
- add_post_meta( $order_id , 'wcal_abandoned_timestamp', $ac_user_id_result[0]->abandoned_cart_time );
394
 
395
  $wpdb->delete( $wcal_guest_ac_table_name, array( 'id' => $wcal_user_id ) );
396
  }
@@ -401,9 +409,9 @@ if ( !class_exists( 'Wcal_Checkout_Process' ) ) {
401
  }
402
  }
403
 
404
- if( 'pending' != $woo_order_status &&
405
- 'failed' != $woo_order_status &&
406
- 'cancelled' != $woo_order_status &&
407
  'trash' != $woo_order_status ) {
408
 
409
  if ( isset( $get_sent_email_id_of_order ) && '' != $get_sent_email_id_of_order ) {
@@ -411,184 +419,185 @@ if ( !class_exists( 'Wcal_Checkout_Process' ) ) {
411
  }
412
  }
413
 
414
- return $woo_order_status;
415
  }
416
 
417
  /**
418
- * Updates the Abandoned Cart History table as well as the
419
- * Email Sent History table to indicate the order has been
420
- * recovered
421
- *
422
- * @param integer $cart_id - ID of the Abandoned Cart
423
- * @param integer $order_id - Recovered Order ID
424
- * @param integer $wcal_check_email_sent_to_cart - ID of the record in the Email Sent History table.
425
- * @param WC_Order $order - Order Details
426
- *
427
- * @since 5.3.0
428
- */
429
- function wcal_updated_recovered_cart( $cart_id, $order_id, $wcal_check_email_sent_to_cart, $order ) {
430
-
431
- global $wpdb;
432
-
433
- $wcal_ac_table_name = $wpdb->prefix . "ac_abandoned_cart_history_lite";
434
- $wcal_email_sent_table = $wpdb->prefix . "ac_sent_history_lite";
435
- $wcal_guest_ac_table = $wpdb->prefix . "ac_guest_abandoned_cart_history_lite";
436
-
437
- // check & make sure that the recovered cart details are not already updated
438
- $query_status = "SELECT recovered_cart FROM `$wcal_ac_table_name` WHERE id = %d";
439
-
440
- $get_status = $wpdb->get_col( $wpdb->prepare( $query_status, $cart_id ) );
441
-
442
- $recovered_status = isset( $get_status[0] ) ? $get_status[0] : '';
443
-
444
- if( $recovered_status == 0 ) {
445
- // Update the cart history table
446
- $update_details = array(
447
- 'recovered_cart' => $order_id,
448
- 'cart_ignored' => '1'
449
- );
450
-
451
- $current_user_id = get_current_user_id();
452
-
453
- if ( $current_user_id !== wcal_common::wcal_get_cart_session( 'user_id' ) &&
454
- $current_user_id != 0 ) {
455
- $update_details['user_id'] = $current_user_id;
456
- }
457
-
458
- // check if more than one reminder email has been sent
459
- $check_emails = "SELECT abandoned_order_id FROM `$wcal_email_sent_table` WHERE id = %d";
460
- $get_old_cart_id = $wpdb->get_col( $wpdb->prepare( $check_emails, $wcal_check_email_sent_to_cart ) );
461
-
462
- $get_ids = array();
463
- if( isset( $get_old_cart_id ) ) {
464
- $query_ids = "SELECT id FROM `$wcal_email_sent_table` WHERE abandoned_order_id = %d";
465
- $get_ids = $wpdb->get_col( $wpdb->prepare( $query_ids, $get_old_cart_id ) );
466
- }
467
-
468
- $update_sent_history = array();
469
-
470
- if ( get_post_meta( $order_id, 'wcal_abandoned_timestamp', true ) != '' ) {
471
- $update_details['abandoned_cart_time'] = get_post_meta( $order_id, 'wcal_abandoned_timestamp', true );
472
-
473
- $update_sent_history['abandoned_order_id'] = $cart_id;
474
-
475
- delete_post_meta( $order_id, 'wcal_abandoned_timestamp', $update_details['abandoned_cart_time'] );
476
- }
477
-
478
- $wpdb->update( $wcal_ac_table_name, $update_details, array( 'id' => $cart_id ) );
479
-
480
- // update the email sent history table
481
- if( is_array( $get_ids ) && count( $get_ids ) > 1 ) {
482
- $list_ids = implode( ',', $get_ids );
483
- $wpdb->query( "UPDATE `$wcal_email_sent_table` SET abandoned_order_id = $cart_id WHERE id IN ($list_ids)" );
484
- } else if( isset( $update_sent_history['abandoned_order_id'] ) ) {
485
- $wpdb->update(
486
- $wcal_email_sent_table,
487
- $update_sent_history,
488
- array( 'id' => $wcal_check_email_sent_to_cart )
489
- );
490
- }
491
-
492
- // Add Order Note
493
- $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-abandoned-cart' ) );
494
- delete_post_meta( $order_id, 'wcal_abandoned_cart_id' );
495
- delete_post_meta( $order_id, 'wcal_recover_order_placed' );
496
- delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id' );
497
- delete_post_meta( $order_id, 'wcal_recovered_email_sent' );
498
- }
499
- }
500
 
501
  /**
502
- * When customer clicks on the "Place Order" button on the checkout page, it will identify if we need to keep that cart or
503
  * delete it.
 
504
  * @hook woocommerce_checkout_order_processed
505
  * @param int | string $order_id Order id
506
  * @globals mixed $wpdb
507
  * @globals mixed $woocommerce
508
- *
509
  * @since 3.4
510
- */
511
  function wcal_order_placed( $order_id ) {
512
 
513
  global $wpdb;
514
- $email_sent_id = wcal_common::wcal_get_cart_session( 'email_sent_id' );
515
- $abandoned_order_id = wcal_common::wcal_get_cart_session( 'abandoned_cart_id_lite' );
516
- $wcal_user_id_of_guest = wcal_common::wcal_get_cart_session( 'user_id' );
517
 
518
- $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
519
  $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
520
  $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
521
 
522
- $abandoned_order_id_to_save = $abandoned_order_id;
523
- if( $email_sent_id != '' && $email_sent_id > 0 ) { // recovered cart
524
-
525
- if( $abandoned_order_id == '' || $abandoned_order_id == false ) {
526
-
527
- $get_ac_id_query = "SELECT abandoned_order_id FROM `$wcal_sent_email_table_name` WHERE id = %d";
528
- $get_ac_id_results = $wpdb->get_results(
529
- $wpdb->prepare(
530
- $get_ac_id_query,
531
- $email_sent_id
532
- )
533
- );
534
-
535
- $abandoned_order_id_to_save = $get_ac_id_results[0]->abandoned_order_id;
536
- }
537
-
538
- // if user becomes the registered user
539
- if ( ( isset( $_POST['account_password'] ) && $_POST['account_password'] != '' ) ||
540
- ( isset( $_POST['createaccount'] ) && $_POST['createaccount'] != '' ) ||
541
- ( !isset( $_POST['createaccount'] ) && 'no' == get_option( 'woocommerce_enable_guest_checkout' ) ) ) {
542
-
543
- if ( $abandoned_order_id != '' && $wcal_user_id_of_guest != '' ) {
544
- $abandoned_cart_id_new_user = $abandoned_order_id;
545
-
546
- // delete the guest record. As it become the logged in user
547
- $get_ac_id_guest_query = "SELECT id, abandoned_cart_time FROM `$wcal_history_table_name` WHERE user_id = %d ORDER BY id DESC";
548
- $get_ac_id_guest_results = $wpdb->get_results(
549
- $wpdb->prepare(
550
- $get_ac_id_guest_query,
551
- $wcal_user_id_of_guest
552
- )
553
- );
554
-
555
- if( is_array( $get_ac_id_guest_results ) && count( $get_ac_id_guest_results ) > 0 ) {
556
- $abandoned_order_id_of_guest = $get_ac_id_guest_results[0]->id;
557
-
558
- add_post_meta( $order_id , 'wcal_abandoned_timestamp', $get_ac_id_guest_results[0]->abandoned_cart_time );
559
-
560
- $wpdb->delete( $wcal_guest_table_name , array( 'id' => $wcal_user_id_of_guest ) );
561
  $wpdb->delete( $wcal_history_table_name, array( 'id' => $get_ac_id_guest_results[0]->id ) );
562
- }
563
- // it is the new registered users cart id
564
- $abandoned_order_id_to_save = $abandoned_cart_id_new_user;
565
- }
566
- }
567
-
568
- add_post_meta( $order_id , 'wcal_recover_order_placed_sent_id', $email_sent_id );
569
- add_post_meta( $order_id , 'wcal_recover_order_placed', $abandoned_order_id );
570
- }else if ( $abandoned_order_id != '' ){
571
-
572
- if ( ( isset( $_POST['account_password'] ) && $_POST['account_password'] != '' ) ||
573
- ( isset( $_POST['createaccount'] ) && $_POST['createaccount'] != '' ) ||
574
- ( !isset( $_POST['createaccount'] ) && 'no' == get_option( 'woocommerce_enable_guest_checkout' ) ) ) {
575
-
576
- if ( $abandoned_order_id != '' && $wcal_user_id_of_guest != '' ) {
577
- $abandoned_cart_id_new_user = $abandoned_order_id;
578
-
579
- // delete the guest record. As it become the logged in user
580
- $wpdb->delete( $wcal_history_table_name, array( 'user_id' => $wcal_user_id_of_guest ) );
581
- $wpdb->delete( $wcal_guest_table_name , array( 'id' => $wcal_user_id_of_guest ) );
582
-
583
- // it is the new registered users cart id
584
- $abandoned_order_id_to_save = $abandoned_cart_id_new_user;
585
- }
586
- }
587
- }
588
-
589
- add_post_meta( $order_id, 'wcal_abandoned_cart_id', $abandoned_order_id_to_save );
590
  }
591
  }
592
  }
593
 
594
- return new Wcal_Checkout_Process();
1
  <?php
2
  /**
3
  * Checkout Process for Abandoned Cart Lite
4
+ *
5
  * @since 5.3.0
6
  */
7
 
8
  // Exit if accessed directly
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
 
13
+ if ( ! class_exists( 'Wcal_Checkout_Process' ) ) {
14
 
15
  /**
16
  * Process recovered orders
17
  */
18
  class Wcal_Checkout_Process {
19
+
20
  function __construct() {
 
 
 
21
 
22
+ // delete added temp fields after order is placed
23
+ add_filter( 'woocommerce_order_details_after_order_table', array( &$this, 'wcal_action_after_delivery_session' ) );
24
 
25
+ add_action( 'woocommerce_order_status_changed', array( &$this, 'wcal_update_cart_details' ), 10, 3 );
26
+ add_action( 'woocommerce_order_status_changed', array( &$this, 'wcal_send_recovery_email' ), 10, 3 );
27
+
28
+ add_action( 'woocommerce_checkout_order_processed', array( &$this, 'wcal_order_placed' ), 10, 1 );
29
+ add_filter( 'woocommerce_payment_complete_order_status', array( &$this, 'wcal_order_complete_action' ), 10, 2 );
30
  }
31
 
32
  /**
33
+ * When user places the order and reach the order recieved page, then it will check if it is abandoned cart and subsequently
34
  * recovered or not.
35
+ *
36
  * @hook woocommerce_order_details_after_order_table
37
  * @param array | object $order Order details
38
  * @globals mixed $wpdb
41
  */
42
  function wcal_action_after_delivery_session( $order ) {
43
 
44
+ $order_id = $order->get_id();
45
+
46
+ $wcal_get_order_status = $order->get_status();
47
+
48
+ $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
49
+ $get_sent_email_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', true );
50
+
51
+ if ( isset( $get_sent_email_id_of_order ) && '' != $get_sent_email_id_of_order ) {
52
+ /**
53
+ * When Placed order button is clicked,
54
+ * we create post meta for that order.
55
+ * If that meta is found then update our plugin table for recovered cart
56
+ */
57
+ $this->wcal_updated_recovered_cart_table( $get_abandoned_id_of_order, $order_id, $get_sent_email_id_of_order, $order );
58
+ } elseif ( '' != $get_abandoned_id_of_order && isset( $get_abandoned_id_of_order ) ) {
59
+ /**
60
+ * if order status is not pending or failed then
61
+ * we will delete the abandoned cart record.
62
+ * post meta will be created only if the cut off time has been reached.
63
+ */
64
+ $this->wcal_delete_abanadoned_data_on_order_status( $order_id, $get_abandoned_id_of_order, $wcal_get_order_status );
65
+ }
66
+
67
+ if ( wcal_common::wcal_get_cart_session( 'email_sent_id' ) != '' ) {
68
+ wcal_common::wcal_unset_cart_session( 'email_sent_id' );
69
+ }
70
  }
71
 
72
  /**
73
+ * If customer had placed the order after cut off time and reached the order recived page then it will also delete the abandoned cart if the order status is not pending or failed.
74
+ *
75
+ * @param int | string $order_id Order id
76
+ * @param int | string $get_abandoned_id_of_order Abandoned cart id
77
+ * @param string $wcal_get_order_status Order status
78
+ * @globals mixed $wpdb
79
+ * @globals mixed $woocommerce
80
+ * @since 5.0
81
+ */
82
+ function wcal_delete_abanadoned_data_on_order_status( $order_id, $get_abandoned_id_of_order, $wcal_get_order_status ) {
83
+
84
+ global $wpdb, $woocommerce;
85
+
86
+ $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
87
  $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
88
  $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
89
 
90
+ if ( 'pending' != $wcal_get_order_status || 'failed' != $wcal_get_order_status ) {
91
+ if ( isset( $get_abandoned_id_of_order ) && '' != $get_abandoned_id_of_order ) {
92
+
93
+ $user_id_query = "SELECT user_id FROM `$wcal_history_table_name` WHERE id = %d";
94
+ $user_id_results = $wpdb->get_results(
95
+ $wpdb->prepare(
96
+ $user_id_query,
97
+ $get_abandoned_id_of_order
98
+ )
99
+ );
100
+
101
+ if ( count( $user_id_results ) > 0 ) {
102
+ $wcal_user_id = $user_id_results[0]->user_id;
103
+
104
+ if ( $wcal_user_id >= 63000000 ) {
105
+ $wpdb->delete( $wcal_guest_table_name, array( 'id' => $wcal_user_id ) );
106
+ }
107
+
108
+ $wpdb->delete( $wcal_history_table_name, array( 'id' => $get_abandoned_id_of_order ) );
109
+ delete_post_meta( $order_id, 'wcal_recover_order_placed', $get_abandoned_id_of_order );
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Updates the Abandoned Cart History table as well as the
117
+ * Email Sent History table to indicate the order has been
118
+ * recovered
119
+ *
120
+ * @param integer $cart_id - ID of the Abandoned Cart
121
+ * @param integer $order_id - Recovered Order ID
122
+ * @param integer $wcal_check_email_sent_to_cart - ID of the record in the Email Sent History table.
123
+ * @param WC_Order $order - Order Details
124
+ *
125
+ * @since 7.7
126
+ */
127
+ function wcal_updated_recovered_cart_table( $cart_id, $order_id, $wcal_check_email_sent_to_cart, $order ) {
128
+
129
+ global $wpdb;
130
+
131
+ $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
132
  $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
133
  $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
134
 
135
+ // check & make sure that the recovered cart details are not already updated
136
+ $query_status = "SELECT recovered_cart FROM `$wcal_history_table_name` WHERE id = %d";
137
+
138
+ $get_status = $wpdb->get_col(
139
+ $wpdb->prepare(
140
+ $query_status,
141
+ $cart_id
142
+ )
143
+ );
144
+
145
+ $recovered_status = isset( $get_status[0] ) ? $get_status[0] : '';
146
+
147
+ if ( $recovered_status == 0 ) {
148
+
149
+ // Update the cart history table
150
+ $update_details = array(
151
+ 'recovered_cart' => $order_id,
152
+ 'cart_ignored' => '1',
153
+ );
154
+
155
+ $current_user_id = get_current_user_id();
156
+
157
+ if ( $current_user_id !== wcal_common::wcal_get_cart_session( 'user_id' ) &&
158
+ $current_user_id != 0 ) {
159
+ $update_details['user_id'] = $current_user_id;
160
+ }
161
+
162
+ // check if more than one reminder email has been sent
163
+ $check_emails = "SELECT abandoned_order_id FROM `$wcal_sent_email_table_name` WHERE id = %d";
164
+ $get_old_cart_id = $wpdb->get_col(
165
+ $wpdb->prepare(
166
+ $check_emails,
167
+ $wcal_check_email_sent_to_cart
168
+ )
169
+ );
170
+
171
+ $get_ids = array();
172
+ if ( isset( $get_old_cart_id ) ) {
173
+ $query_ids = "SELECT id FROM `$wcal_sent_email_table_name` WHERE abandoned_order_id = %d";
174
+ $get_ids = $wpdb->get_col( $wpdb->prepare( $query_ids, $get_old_cart_id ) );
175
+ }
176
+
177
+ $update_sent_history = array();
178
+
179
+ if ( get_post_meta( $order_id, 'wcal_abandoned_timestamp', true ) != '' ) {
180
+ $update_details['abandoned_cart_time'] = get_post_meta( $order_id, 'wcal_abandoned_timestamp', true );
181
+
182
+ $update_sent_history['abandoned_order_id'] = $cart_id;
183
+
184
+ delete_post_meta( $order_id, 'wcal_abandoned_timestamp', $update_details['abandoned_cart_time'] );
185
+ }
186
+
187
+ $wpdb->update( $wcal_history_table_name, $update_details, array( 'id' => $cart_id ) );
188
+
189
+ // update the email sent history table
190
+ if ( is_array( $get_ids ) && count( $get_ids ) > 1 ) {
191
+ $list_ids = implode( ',', $get_ids );
192
+ $wpdb->query( "UPDATE `$wcal_sent_email_table_name` SET abandoned_order_id = $cart_id WHERE id IN ($list_ids)" );
193
+ } elseif ( isset( $update_sent_history['abandoned_order_id'] ) ) {
194
+ $wpdb->update(
195
+ $wcal_sent_email_table_name,
196
+ $update_sent_history,
197
+ array( 'id' => $wcal_check_email_sent_to_cart )
198
+ );
199
+ }
200
+
201
+ // Add Order Note
202
+ $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-abandoned-cart' ) );
203
+ delete_post_meta( $order_id, 'wcal_abandoned_cart_id' );
204
+ delete_post_meta( $order_id, 'wcal_recover_order_placed' );
205
+ delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id' );
206
+ delete_post_meta( $order_id, 'wcal_recovered_email_sent' );
207
+ }
208
+ }
209
 
210
  /**
211
  * Send email to admin when cart is recovered only via PayPal.
212
+ *
213
  * @hook woocommerce_order_status_changed
214
  * @param int | string $order_id Order id
215
+ * @param string $wc_old_status Old status
216
+ * @param string $wc_new_status New status
217
  * @globals mixed $wpdb
218
  * @globals mixed $woocommerce
219
  * @since 2.9
220
  */
221
  public function wcal_update_cart_details( $order_id, $wc_old_status, $wc_new_status ) {
222
 
223
+ if ( 'pending' != $wc_new_status &&
224
+ 'failed' != $wc_new_status &&
225
+ 'cancelled' != $wc_new_status &&
226
+ 'trash' != $wc_new_status ) {
227
+
228
+ global $wpdb;
229
 
230
+ $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
231
  $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
232
  $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
233
 
234
+ if ( $order_id > 0 ) {
235
+ $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
236
+
237
+ if ( $get_abandoned_id_of_order > 0 || wcal_common::wcal_get_cart_session( 'email_sent_id' ) != '' ) {
238
  // recovered order
239
+ } else {
240
+
241
+ $wcal_abandoned_id = get_post_meta( $order_id, 'wcal_abandoned_cart_id', true );
242
+
243
+ // check if it's a guest cart
244
+ $query_cart_data = "SELECT user_id, user_type FROM `$wcal_history_table_name` WHERE id = %d";
245
+ $get_cart_data = $wpdb->get_results(
246
+ $wpdb->prepare(
247
+ $query_cart_data,
248
+ $wcal_abandoned_id
249
+ )
250
+ );
251
+
252
+ if ( is_array( $get_cart_data ) && count( $get_cart_data ) > 0 ) {
253
+ $user_type = $get_cart_data[0]->user_type;
254
+ $user_id = $get_cart_data[0]->user_id;
255
+
256
+ if ( 'GUEST' == $user_type && $user_id >= 63000000 ) {
257
+ $wpdb->delete( $wcal_guest_table_name, array( 'id' => $user_id ) );
258
+ }
259
+ }
260
+ $wpdb->delete( $wcal_history_table_name, array( 'id' => $wcal_abandoned_id ) );
261
+ }
262
+ }
263
+ } elseif ( 'pending' == $wc_old_status && 'cancelled' == $wc_new_status ) {
264
+ global $wpdb;
265
+
266
+ $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
267
+ $wcal_abandoned_id = get_post_meta( $order_id, 'wcal_abandoned_cart_id', true );
268
 
269
  $wpdb->update( $wcal_history_table_name, array( 'cart_ignored' => '1' ), array( 'id' => $wcal_abandoned_id ) );
270
  }
271
  }
272
 
273
  /**
274
+ * This function will send the email to the store admin when any abandoned cart email recovered.
275
+ *
276
+ * @hook woocommerce_order_status_changed
277
+ * @param int | string $order_id Order id
278
+ * @param string $wcap_old_status Old status of the order
279
+ * @param string $wcap_new_status New status of the order
280
+ * @globals mixed $woocommerce
281
+ * @since 1.0
282
+ */
283
+ function wcal_send_recovery_email( $order_id, $wcap_old_status, $wcap_new_status ) {
284
+ global $woocommerce;
285
+
286
+ if ( ( 'pending' == $wcap_old_status && 'processing' == $wcap_new_status )
287
+ || ( 'pending' == $wcap_old_status && 'completed' == $wcap_new_status )
288
+ || ( 'pending' == $wcap_old_status && 'on-hold' == $wcap_new_status )
289
+ || ( 'failed' == $wcap_old_status && 'completed' == $wcap_new_status )
290
+ || ( 'failed' == $wcap_old_status && 'processing' == $wcap_new_status )
291
+ ) {
292
+ $user_id = get_current_user_id();
293
+ $ac_email_admin_recovery = get_option( 'ac_lite_email_admin_on_recovery' );
294
+ $order = wc_get_order( $order_id );
295
+ if ( version_compare( $woocommerce->version, '3.0.0', '>=' ) ) {
296
+ $user_id = $order->get_user_id();
297
+ } else {
298
+ $user_id = $order->user_id;
299
+ }
300
+ if ( $ac_email_admin_recovery == 'on' ) {
301
+ $recovered_email_sent = get_post_meta( $order_id, 'wcal_recovered_email_sent', true );
302
+ $wcal_check_order_is_recovered = $this->wcal_check_order_is_recovered( $order_id );
303
+
304
+ if ( 'yes' != $recovered_email_sent && true === $wcal_check_order_is_recovered ) { // indicates cart is abandoned
305
+ $order = wc_get_order( $order_id );
306
+ $email_heading = __( 'New Customer Order - Recovered', 'woocommerce' );
307
+ $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
308
+ $email_subject = __( 'New Customer Order - Recovered', 'woocommerce' );
309
+ $user_email = get_option( 'admin_email' );
310
+ $headers[] = 'From: Admin <' . $user_email . '>';
311
+ $headers[] = 'Content-Type: text/html';
312
+ // Buffer
313
+ ob_start();
314
+ // Get mail template
315
+ wc_get_template(
316
+ 'emails/admin-new-order.php',
317
+ array(
318
  'order' => $order,
319
  'email_heading' => $email_heading,
320
+ 'sent_to_admin' => false,
321
+ 'plain_text' => false,
322
+ 'email' => true,
323
+ )
324
+ );
325
+ // Get contents
326
+ $email_body = ob_get_clean();
327
  wc_mail( $user_email, $email_subject, $email_body, $headers );
328
 
329
  update_post_meta( $order_id, 'wcal_recovered_email_sent', 'yes' );
334
 
335
  /**
336
  * For sending Recovery Email to Admin, we will check that order is recovered or not.
337
+ *
338
  * @param int | string $wcal_order_id Order id
339
  * @return boolean true | false
340
  * @globals mixed $wpdb
342
  */
343
  function wcal_check_order_is_recovered( $wcal_order_id ) {
344
  global $wpdb;
345
+ $wcal_recover_order_query = 'SELECT recovered_cart FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE recovered_cart = %d';
346
  $wcal_recover_order_query_result = $wpdb->get_results( $wpdb->prepare( $wcal_recover_order_query, $wcal_order_id ) );
347
  if ( count( $wcal_recover_order_query_result ) > 0 ) {
348
  return true;
351
  }
352
 
353
  /**
354
+ * It will check the WooCommerce order status. If the order status is pending or failed the we will keep that cart record
355
  * as an abandoned cart.
356
  * It will be executed after order placed.
357
+ *
358
  * @hook woocommerce_payment_complete_order_status
359
+ * @param string $order_status Order Status
360
  * @param int | string $order_id Order Id
361
  * @return string $order_status
362
  * @globals mixed $wpdb
371
  $get_abandoned_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed', true );
372
  $get_sent_email_id_of_order = get_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', true );
373
 
374
+ // Order Status passed in the function is either
375
+ // 'processing' or 'complete' and may or may not reflect the actual order status.
376
+ // Hence, always use the status fetched from the order object.
377
 
378
+ $order_status = ( $order ) ? $order->get_status() : '';
379
 
380
+ $wcal_ac_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
381
+ $wcal_email_sent_history_table_name = $wpdb->prefix . 'ac_sent_history_lite';
382
+ $wcal_guest_ac_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
383
 
384
+ if ( 'pending' != $order_status && 'failed' != $order_status && 'cancelled' != $order_status && 'trash' != $order_status ) {
385
+ global $wpdb;
386
 
387
+ if ( isset( $get_abandoned_id_of_order ) && '' != $get_abandoned_id_of_order ) {
388
 
389
+ $ac_user_id_query = "SELECT user_id, abandoned_cart_time FROM `$wcal_ac_table_name` WHERE id = %d";
390
+ $ac_user_id_result = $wpdb->get_results(
391
+ $wpdb->prepare(
392
+ $ac_user_id_query,
393
+ $get_abandoned_id_of_order
394
+ )
395
+ );
396
 
397
+ if ( count( $ac_user_id_result ) > 0 ) {
398
  $wcal_user_id = $ac_user_id_result[0]->user_id;
399
 
400
+ if ( $wcal_user_id >= 63000000 ) {
401
+ add_post_meta( $order_id, 'wcal_abandoned_timestamp', $ac_user_id_result[0]->abandoned_cart_time );
402
 
403
  $wpdb->delete( $wcal_guest_ac_table_name, array( 'id' => $wcal_user_id ) );
404
  }
409
  }
410
  }
411
 
412
+ if ( 'pending' != $woo_order_status &&
413
+ 'failed' != $woo_order_status &&
414
+ 'cancelled' != $woo_order_status &&
415
  'trash' != $woo_order_status ) {
416
 
417
  if ( isset( $get_sent_email_id_of_order ) && '' != $get_sent_email_id_of_order ) {
419
  }
420
  }
421
 
422
+ return $woo_order_status;
423
  }
424
 
425
  /**
426
+ * Updates the Abandoned Cart History table as well as the
427
+ * Email Sent History table to indicate the order has been
428
+ * recovered
429
+ *
430
+ * @param integer $cart_id - ID of the Abandoned Cart
431
+ * @param integer $order_id - Recovered Order ID
432
+ * @param integer $wcal_check_email_sent_to_cart - ID of the record in the Email Sent History table.
433
+ * @param WC_Order $order - Order Details
434
+ *
435
+ * @since 5.3.0
436
+ */
437
+ function wcal_updated_recovered_cart( $cart_id, $order_id, $wcal_check_email_sent_to_cart, $order ) {
438
+
439
+ global $wpdb;
440
+
441
+ $wcal_ac_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
442
+ $wcal_email_sent_table = $wpdb->prefix . 'ac_sent_history_lite';
443
+ $wcal_guest_ac_table = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
444
+
445
+ // check & make sure that the recovered cart details are not already updated
446
+ $query_status = "SELECT recovered_cart FROM `$wcal_ac_table_name` WHERE id = %d";
447
+
448
+ $get_status = $wpdb->get_col( $wpdb->prepare( $query_status, $cart_id ) );
449
+
450
+ $recovered_status = isset( $get_status[0] ) ? $get_status[0] : '';
451
+
452
+ if ( $recovered_status == 0 ) {
453
+ // Update the cart history table
454
+ $update_details = array(
455
+ 'recovered_cart' => $order_id,
456
+ 'cart_ignored' => '1',
457
+ );
458
+
459
+ $current_user_id = get_current_user_id();
460
+
461
+ if ( $current_user_id !== wcal_common::wcal_get_cart_session( 'user_id' ) &&
462
+ $current_user_id != 0 ) {
463
+ $update_details['user_id'] = $current_user_id;
464
+ }
465
+
466
+ // check if more than one reminder email has been sent
467
+ $check_emails = "SELECT abandoned_order_id FROM `$wcal_email_sent_table` WHERE id = %d";
468
+ $get_old_cart_id = $wpdb->get_col( $wpdb->prepare( $check_emails, $wcal_check_email_sent_to_cart ) );
469
+
470
+ $get_ids = array();
471
+ if ( isset( $get_old_cart_id ) ) {
472
+ $query_ids = "SELECT id FROM `$wcal_email_sent_table` WHERE abandoned_order_id = %d";
473
+ $get_ids = $wpdb->get_col( $wpdb->prepare( $query_ids, $get_old_cart_id ) );
474
+ }
475
+
476
+ $update_sent_history = array();
477
+
478
+ if ( get_post_meta( $order_id, 'wcal_abandoned_timestamp', true ) != '' ) {
479
+ $update_details['abandoned_cart_time'] = get_post_meta( $order_id, 'wcal_abandoned_timestamp', true );
480
+
481
+ $update_sent_history['abandoned_order_id'] = $cart_id;
482
+
483
+ delete_post_meta( $order_id, 'wcal_abandoned_timestamp', $update_details['abandoned_cart_time'] );
484
+ }
485
+
486
+ $wpdb->update( $wcal_ac_table_name, $update_details, array( 'id' => $cart_id ) );
487
+
488
+ // update the email sent history table
489
+ if ( is_array( $get_ids ) && count( $get_ids ) > 1 ) {
490
+ $list_ids = implode( ',', $get_ids );
491
+ $wpdb->query( "UPDATE `$wcal_email_sent_table` SET abandoned_order_id = $cart_id WHERE id IN ($list_ids)" );
492
+ } elseif ( isset( $update_sent_history['abandoned_order_id'] ) ) {
493
+ $wpdb->update(
494
+ $wcal_email_sent_table,
495
+ $update_sent_history,
496
+ array( 'id' => $wcal_check_email_sent_to_cart )
497
+ );
498
+ }
499
+
500
+ // Add Order Note
501
+ $order->add_order_note( __( 'This order was abandoned & subsequently recovered.', 'woocommerce-abandoned-cart' ) );
502
+ delete_post_meta( $order_id, 'wcal_abandoned_cart_id' );
503
+ delete_post_meta( $order_id, 'wcal_recover_order_placed' );
504
+ delete_post_meta( $order_id, 'wcal_recover_order_placed_sent_id' );
505
+ delete_post_meta( $order_id, 'wcal_recovered_email_sent' );
506
+ }
507
+ }
508
 
509
  /**
510
+ * When customer clicks on the "Place Order" button on the checkout page, it will identify if we need to keep that cart or
511
  * delete it.
512
+ *
513
  * @hook woocommerce_checkout_order_processed
514
  * @param int | string $order_id Order id
515
  * @globals mixed $wpdb
516
  * @globals mixed $woocommerce
517
+ *
518
  * @since 3.4
519
+ */
520
  function wcal_order_placed( $order_id ) {
521
 
522
  global $wpdb;
523
+ $email_sent_id = wcal_common::wcal_get_cart_session( 'email_sent_id' );
524
+ $abandoned_order_id = wcal_common::wcal_get_cart_session( 'abandoned_cart_id_lite' );
525
+ $wcal_user_id_of_guest = wcal_common::wcal_get_cart_session( 'user_id' );
526
 
527
+ $wcal_history_table_name = $wpdb->prefix . 'ac_abandoned_cart_history_lite';
528
  $wcal_guest_table_name = $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite';
529
  $wcal_sent_email_table_name = $wpdb->prefix . 'ac_sent_history_lite';
530
 
531
+ $abandoned_order_id_to_save = $abandoned_order_id;
532
+ if ( $email_sent_id != '' && $email_sent_id > 0 ) { // recovered cart
533
+
534
+ if ( $abandoned_order_id == '' || $abandoned_order_id == false ) {
535
+
536
+ $get_ac_id_query = "SELECT abandoned_order_id FROM `$wcal_sent_email_table_name` WHERE id = %d";
537
+ $get_ac_id_results = $wpdb->get_results(
538
+ $wpdb->prepare(
539
+ $get_ac_id_query,
540
+ $email_sent_id
541
+ )
542
+ );
543
+
544
+ $abandoned_order_id_to_save = $get_ac_id_results[0]->abandoned_order_id;
545
+ }
546
+
547
+ // if user becomes the registered user
548
+ if ( ( isset( $_POST['account_password'] ) && $_POST['account_password'] != '' ) ||
549
+ ( isset( $_POST['createaccount'] ) && $_POST['createaccount'] != '' ) ||
550
+ ( ! isset( $_POST['createaccount'] ) && 'no' == get_option( 'woocommerce_enable_guest_checkout' ) ) ) {
551
+
552
+ if ( $abandoned_order_id != '' && $wcal_user_id_of_guest != '' ) {
553
+ $abandoned_cart_id_new_user = $abandoned_order_id;
554
+
555
+ // delete the guest record. As it become the logged in user
556
+ $get_ac_id_guest_query = "SELECT id, abandoned_cart_time FROM `$wcal_history_table_name` WHERE user_id = %d ORDER BY id DESC";
557
+ $get_ac_id_guest_results = $wpdb->get_results(
558
+ $wpdb->prepare(
559
+ $get_ac_id_guest_query,
560
+ $wcal_user_id_of_guest
561
+ )
562
+ );
563
+
564
+ if ( is_array( $get_ac_id_guest_results ) && count( $get_ac_id_guest_results ) > 0 ) {
565
+ $abandoned_order_id_of_guest = $get_ac_id_guest_results[0]->id;
566
+
567
+ add_post_meta( $order_id, 'wcal_abandoned_timestamp', $get_ac_id_guest_results[0]->abandoned_cart_time );
568
+
569
+ $wpdb->delete( $wcal_guest_table_name, array( 'id' => $wcal_user_id_of_guest ) );
570
  $wpdb->delete( $wcal_history_table_name, array( 'id' => $get_ac_id_guest_results[0]->id ) );
571
+ }
572
+ // it is the new registered users cart id
573
+ $abandoned_order_id_to_save = $abandoned_cart_id_new_user;
574
+ }
575
+ }
576
+
577
+ add_post_meta( $order_id, 'wcal_recover_order_placed_sent_id', $email_sent_id );
578
+ add_post_meta( $order_id, 'wcal_recover_order_placed', $abandoned_order_id );
579
+ } elseif ( $abandoned_order_id != '' ) {
580
+
581
+ if ( ( isset( $_POST['account_password'] ) && $_POST['account_password'] != '' ) ||
582
+ ( isset( $_POST['createaccount'] ) && $_POST['createaccount'] != '' ) ||
583
+ ( ! isset( $_POST['createaccount'] ) && 'no' == get_option( 'woocommerce_enable_guest_checkout' ) ) ) {
584
+
585
+ if ( $abandoned_order_id != '' && $wcal_user_id_of_guest != '' ) {
586
+ $abandoned_cart_id_new_user = $abandoned_order_id;
587
+
588
+ // delete the guest record. As it become the logged in user
589
+ $wpdb->delete( $wcal_history_table_name, array( 'user_id' => $wcal_user_id_of_guest ) );
590
+ $wpdb->delete( $wcal_guest_table_name, array( 'id' => $wcal_user_id_of_guest ) );
591
+
592
+ // it is the new registered users cart id
593
+ $abandoned_order_id_to_save = $abandoned_cart_id_new_user;
594
+ }
595
+ }
596
+ }
597
+
598
+ add_post_meta( $order_id, 'wcal_abandoned_cart_id', $abandoned_order_id_to_save );
599
  }
600
  }
601
  }
602
 
603
+ return new Wcal_Checkout_Process();
includes/frontend/wcal_frontend.php CHANGED
@@ -1,30 +1,32 @@
1
  <?php
2
  /**
3
  * Frontend loader for Abandoned Cart Lite
4
- *
5
  * @since 5.3.0
6
  */
7
 
8
  // Exit if accessed directly
9
- if ( !defined( 'ABSPATH' ) ) exit;
 
 
10
 
11
- if ( !class_exists( 'Wcal_Frontend' ) ) {
12
 
13
  /**
14
  * Frontend loader
15
  */
16
  class Wcal_Frontend {
17
-
18
  function __construct() {
19
-
20
  $this->include_files();
21
  }
22
 
23
  function include_files() {
24
-
25
  include_once 'wcal_checkout_process.php';
26
  }
27
  }
28
  }
29
 
30
- return new Wcal_Frontend();
1
  <?php
2
  /**
3
  * Frontend loader for Abandoned Cart Lite
4
+ *
5
  * @since 5.3.0
6
  */
7
 
8
  // Exit if accessed directly
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
 
13
+ if ( ! class_exists( 'Wcal_Frontend' ) ) {
14
 
15
  /**
16
  * Frontend loader
17
  */
18
  class Wcal_Frontend {
19
+
20
  function __construct() {
21
+
22
  $this->include_files();
23
  }
24
 
25
  function include_files() {
26
+
27
  include_once 'wcal_checkout_process.php';
28
  }
29
  }
30
  }
31
 
32
+ return new Wcal_Frontend();
includes/templates/template_1.php CHANGED
@@ -1,144 +1,145 @@
1
  <?php
2
 
3
- $site_title = get_bloginfo( 'name' );
4
- $site_url = get_option( 'siteurl' );
5
- $admin_args = array( 'role' => 'administrator',
6
- 'fields' => array( 'id' )
7
- );
 
8
 
9
- $admin_usr = get_users( $admin_args );
10
- $uid = $admin_usr[0]->id;
11
  $admin_phone = get_user_meta( $uid, 'billing_phone', true );
12
  ?>
13
 
14
  <p><style type="text/css">
15
- * {
16
- -webkit-font-smoothing: antialiased;
17
- }
18
- div, p, a, li, td {
19
- -webkit-text-size-adjust: none;
20
- }
21
- #outlook a {
22
- padding: 0;
23
- }
24
- html {
25
- width: 100%;
26
- }
27
- body {
28
- margin: 0;
29
- padding: 0;
30
- color: #808080;
31
- width: 100% !important;
32
- font-family: Arial, Helvetica, sans-serif;
33
- -webkit-text-size-adjust: 100%!important;
34
- -ms-text-size-adjust: 100%!important;
35
- -webkit-font-smoothing: antialiased!important;
36
- }
37
- img {
38
- outline: none;
39
- border: none;
40
- text-decoration: none;
41
- -ms-interpolation-mode: bicubic;
42
- }
43
- a {
44
- text-decoration: none;
45
- }
46
- a img {
47
- border: none;
48
- }
49
- table {
50
- color: #222222;
51
- font-family: Arial, sans-serif;
52
- }
53
- table td {
54
- border-collapse: collapse;
55
- mso-line-height-rule: exactly;
56
- mso-table-lspace: 0pt;
57
- mso-table-rspace: 0pt;
58
- }
59
- table {
60
- border-collapse: collapse;
61
- mso-table-lspace: 0pt;
62
- mso-table-rspace: 0pt;
63
- }
64
- .main-wrapper {
65
- max-width: 600px;
66
- }
67
- .container {
68
- width: 100%;
69
- table-layout: fixed;
70
- -webkit-text-size-adjust: 100%;
71
- -ms-text-size-adjust: 100%;
72
- }
73
- @media screen and (max-device-width:600px),
74
- screen and (max-width:600px) {
75
- td[class=td_em_hide] {
76
- display: none !important;
77
- }
78
- table[class=main-wrapper] {
79
- width: 100%!important;
80
- }
81
- td[class=em_bg_center] {
82
- background-position: center!important;
83
- }
84
- .main-wrapper {
85
- width: 100% !important;
86
- }
87
- }
88
- @media screen and (max-device-width:520px),
89
- screen and (max-width:520px) {
90
- td[class=td_w_sm] {
91
- width: 20px!important;
92
- }
93
- td[class=td_sm_hide] {
94
- display: none !important;
95
- }
96
- .sm-center-txt {
97
- text-align: center;
98
- }
99
- table[class=main-wrapper] {
100
- width: 100%!important;
101
- }
102
- table[class=sm_wrapper] {
103
- width: 100%!important;
104
- }
105
- td[class=td-sm_wrapper] {
106
- width: 100%!important;
107
- }
108
- td[class=sm-txt] {
109
- font-size: 24px!important;
110
- }
111
- td[class=sm-txt1] {
112
- font-size: 45px!important;
113
- }
114
- .main-wrapper {
115
- width: 100% !important;
116
- }
117
- }
118
- </style></p><p><style type="text/css">
119
- @media only screen and (max-width:480px) {
120
- @-ms-viewport {
121
- width: 320px;
122
- }
123
- @viewport {
124
- width: 320px;
125
- }
126
- }
127
- </style></p><p><style type="text/css">
128
- @import url(https://fonts.googleapis.com/css?family=Lato);
129
- @import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);
130
- @import url(https://fonts.googleapis.com/css?family=Cabin);
131
- </style></p><table style="background-color: #f6f3f3; font-size: 15px; line-height: 20px; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt;" border="0" width="100%" cellspacing="0" cellpadding="0" bgcolor="#f6f3f3"><tbody><tr><td align="center" valign="top" width="100%"><!-- [if mso | IE]>
132
- <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" align="center" style="width:600px;">
133
- <tr>
134
- <td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
135
- <![endif]--><div style="margin: 0 auto; max-width: 600px;"><table class="main-wrapper" style="background-color: #ffffff; table-layout: fixed; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-family: Arial, Helvetica, sans-serif; color: #333333; margin: 0 auto; max-width: 600px;" role="presentation" border="0" cellspacing="0" cellpadding="0" align="center" bgcolor="#ffffff"><tbody><tr><td style="padding-top: 10px;" bgcolor="#ffffff" width="100%"><table border="0" width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td class="td_w_sm" style="font-size: 0; line-height: 0;" width="30"> </td><td style="padding: 0;"><div style="font-size: 0pt; line-height: 0pt; height: 20px;"> </div><table border="0" width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td class="sm-txt" style="font-size: 30px; line-height: 30px; text-align: center; color: #333032; text-transform: uppercase; font-family: Ubuntu, Helvetica, Arial, sans-serif, Helvetica, Arial, sans-serif; padding: 0;" align="center" width="100%"><?php echo "$site_title"; ?> </td>
136
 
137
- </tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td class="sm-txt1" style="font-size: 50px; line-height: 50px; text-align: center; color: #000000; text-transform: uppercase; font-family: Ubuntu, Helvetica, Arial, sans-serif, Helvetica, Arial, sans-serif; padding: 0;" align="center" width="100%">PSST...</td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="20"> </td></tr><tr><td style="font-size: 15px; line-height: 24px; text-align: center; color: #333032; text-transform: uppercase; letter-spacing: 2px; padding: 0;" align="center" width="100%">Looks like you left something fabulous <br />in your shopping bag</td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="25"> </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; padding: 0;" align="center"><img style="display: block; width: 100%; max-width: 301px; margin: 0 auto;" src="http://staging.tychesoftwares.com/templates/default1.jpeg" alt="" /></td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="25"> </td></tr><tr><td style="font-size: 15px; line-height: 24px; text-align: center; color: #333032; text-transform: uppercase; letter-spacing: 2px; padding: 0;" align="center" width="100%">Shop now before time runs out, <br />These must have ITEMs won't be around for long... </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="20"> </td></tr><tr><td style="text-align: center; padding: 0;" align="center">
138
 
139
- {{products.cart}}
140
 
141
 
142
- </td></tr><tr><td style="line-height: 1px; font-size: 1px;" bgcolor="#cfcfcf" height="2"> </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td style="font-size: 15px; line-height: 20px; text-align: center; color: #333032; font-weight: bold; padding: 0;" align="center" width="100%">For your convenience, we have saved your shopping cart.</td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td align="center"><table border="0" cellspacing="0" cellpadding="0" align="center"><tbody><tr><td align="center"><table border="0" width="270" cellspacing="0" cellpadding="0" align="center"><tbody><tr><td style="border-collapse: collapse; word-break: break-word; word-wrap: break-word;" align="center"><a style="display: block; font-family: Arial, Helvetica, sans-serif; font-size: 16px; letter-spacing: 1px; color: #ffffff; line-height: 20px; text-decoration: none; text-align: center; background-color: #000; margin: 0 auto; width: 270px; box-sizing: border-box; padding: 8px 8px 8px 8px;" href="{{cart.link}}">CHECKOUT NOW</a></td></tr></tbody></table></td></tr></tbody></table></td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td style="font-size: 15px; line-height: 20px; text-align: center; color: #333032; padding: 0;" align="center" width="100%">For your assistance or if you would like to place an order directly with our customer service team, please call us at <?php echo "$admin_phone"; ?> </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td style="line-height: 1px; font-size: 1px;" bgcolor="#cfcfcf" height="2"> </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr></tbody></table></td><td class="td_w_sm" style="font-size: 0; line-height: 0;" width="30"> </td></tr></tbody></table></td></tr><tr><td><!-- ======= footer start======= --><table border="0" width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td class="td_w_sm" style="font-size: 0; line-height: 0;" width="30"> </td><td style="padding: 0;"><table border="0" width="100%" cellspacing="0" cellpadding="0"><tbody>
143
 
144
- <td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="10"> </td></tr><tr><td style="font-size: 15px; line-height: 20px; text-align: center; color: #333032; padding: 0;" align="center" width="100%"><a href="{{cart.unsubscribe}}">Unsubscribe</a></td></tr></tbody></table><!-- ======= footer end======= --></td><td class="td_w_sm" style="font-size: 0; line-height: 0;" width="30"> </td></tr></tbody></table></td></tr></tbody></table></div><!-- [if mso | IE]> </td></tr></table> <![endif]--></td></tr></tbody></table>
1
  <?php
2
 
3
+ $site_title = get_bloginfo( 'name' );
4
+ $site_url = get_option( 'siteurl' );
5
+ $admin_args = array(
6
+ 'role' => 'administrator',
7
+ 'fields' => array( 'id' ),
8
+ );
9
 
10
+ $admin_usr = get_users( $admin_args );
11
+ $uid = $admin_usr[0]->id;
12
  $admin_phone = get_user_meta( $uid, 'billing_phone', true );
13
  ?>
14
 
15
  <p><style type="text/css">
16
+ * {
17
+ -webkit-font-smoothing: antialiased;
18
+ }
19
+ div, p, a, li, td {
20
+ -webkit-text-size-adjust: none;
21
+ }
22
+ #outlook a {
23
+ padding: 0;
24
+ }
25
+ html {
26
+ width: 100%;
27
+ }
28
+ body {
29
+ margin: 0;
30
+ padding: 0;
31
+ color: #808080;
32
+ width: 100% !important;
33
+ font-family: Arial, Helvetica, sans-serif;
34
+ -webkit-text-size-adjust: 100%!important;
35
+ -ms-text-size-adjust: 100%!important;
36
+ -webkit-font-smoothing: antialiased!important;
37
+ }
38
+ img {
39
+ outline: none;
40
+ border: none;
41
+ text-decoration: none;
42
+ -ms-interpolation-mode: bicubic;
43
+ }
44
+ a {
45
+ text-decoration: none;
46
+ }
47
+ a img {
48
+ border: none;
49
+ }
50
+ table {
51
+ color: #222222;
52
+ font-family: Arial, sans-serif;
53
+ }
54
+ table td {
55
+ border-collapse: collapse;
56
+ mso-line-height-rule: exactly;
57
+ mso-table-lspace: 0pt;
58
+ mso-table-rspace: 0pt;
59
+ }
60
+ table {
61
+ border-collapse: collapse;
62
+ mso-table-lspace: 0pt;
63
+ mso-table-rspace: 0pt;
64
+ }
65
+ .main-wrapper {
66
+ max-width: 600px;
67
+ }
68
+ .container {
69
+ width: 100%;
70
+ table-layout: fixed;
71
+ -webkit-text-size-adjust: 100%;
72
+ -ms-text-size-adjust: 100%;
73
+ }
74
+ @media screen and (max-device-width:600px),
75
+ screen and (max-width:600px) {
76
+ td[class=td_em_hide] {
77
+ display: none !important;
78
+ }
79
+ table[class=main-wrapper] {
80
+ width: 100%!important;
81
+ }
82
+ td[class=em_bg_center] {
83
+ background-position: center!important;
84
+ }
85
+ .main-wrapper {
86
+ width: 100% !important;
87
+ }
88
+ }
89
+ @media screen and (max-device-width:520px),
90
+ screen and (max-width:520px) {
91
+ td[class=td_w_sm] {
92
+ width: 20px!important;
93
+ }
94
+ td[class=td_sm_hide] {
95
+ display: none !important;
96
+ }
97
+ .sm-center-txt {
98
+ text-align: center;
99
+ }
100
+ table[class=main-wrapper] {
101
+ width: 100%!important;
102
+ }
103
+ table[class=sm_wrapper] {
104
+ width: 100%!important;
105
+ }
106
+ td[class=td-sm_wrapper] {
107
+ width: 100%!important;
108
+ }
109
+ td[class=sm-txt] {
110
+ font-size: 24px!important;
111
+ }
112
+ td[class=sm-txt1] {
113
+ font-size: 45px!important;
114
+ }
115
+ .main-wrapper {
116
+ width: 100% !important;
117
+ }
118
+ }
119
+ </style></p><p><style type="text/css">
120
+ @media only screen and (max-width:480px) {
121
+ @-ms-viewport {
122
+ width: 320px;
123
+ }
124
+ @viewport {
125
+ width: 320px;
126
+ }
127
+ }
128
+ </style></p><p><style type="text/css">
129
+ @import url(https://fonts.googleapis.com/css?family=Lato);
130
+ @import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);
131
+ @import url(https://fonts.googleapis.com/css?family=Cabin);
132
+ </style></p><table style="background-color: #f6f3f3; font-size: 15px; line-height: 20px; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt;" border="0" width="100%" cellspacing="0" cellpadding="0" bgcolor="#f6f3f3"><tbody><tr><td align="center" valign="top" width="100%"><!-- [if mso | IE]>
133
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" align="center" style="width:600px;">
134
+ <tr>
135
+ <td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
136
+ <![endif]--><div style="margin: 0 auto; max-width: 600px;"><table class="main-wrapper" style="background-color: #ffffff; table-layout: fixed; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-family: Arial, Helvetica, sans-serif; color: #333333; margin: 0 auto; max-width: 600px;" role="presentation" border="0" cellspacing="0" cellpadding="0" align="center" bgcolor="#ffffff"><tbody><tr><td style="padding-top: 10px;" bgcolor="#ffffff" width="100%"><table border="0" width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td class="td_w_sm" style="font-size: 0; line-height: 0;" width="30"> </td><td style="padding: 0;"><div style="font-size: 0pt; line-height: 0pt; height: 20px;"> </div><table border="0" width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td class="sm-txt" style="font-size: 30px; line-height: 30px; text-align: center; color: #333032; text-transform: uppercase; font-family: Ubuntu, Helvetica, Arial, sans-serif, Helvetica, Arial, sans-serif; padding: 0;" align="center" width="100%"><?php echo "$site_title"; ?> </td>
137
 
138
+ </tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td class="sm-txt1" style="font-size: 50px; line-height: 50px; text-align: center; color: #000000; text-transform: uppercase; font-family: Ubuntu, Helvetica, Arial, sans-serif, Helvetica, Arial, sans-serif; padding: 0;" align="center" width="100%">PSST...</td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="20"> </td></tr><tr><td style="font-size: 15px; line-height: 24px; text-align: center; color: #333032; text-transform: uppercase; letter-spacing: 2px; padding: 0;" align="center" width="100%">Looks like you left something fabulous <br />in your shopping bag</td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="25"> </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; padding: 0;" align="center"><img style="display: block; width: 100%; max-width: 301px; margin: 0 auto;" src="http://staging.tychesoftwares.com/templates/default1.jpeg" alt="" /></td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="25"> </td></tr><tr><td style="font-size: 15px; line-height: 24px; text-align: center; color: #333032; text-transform: uppercase; letter-spacing: 2px; padding: 0;" align="center" width="100%">Shop now before time runs out, <br />These must have ITEMs won't be around for long... </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="20"> </td></tr><tr><td style="text-align: center; padding: 0;" align="center">
139
 
140
+ {{products.cart}}
141
 
142
 
143
+ </td></tr><tr><td style="line-height: 1px; font-size: 1px;" bgcolor="#cfcfcf" height="2"> </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td style="font-size: 15px; line-height: 20px; text-align: center; color: #333032; font-weight: bold; padding: 0;" align="center" width="100%">For your convenience, we have saved your shopping cart.</td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td align="center"><table border="0" cellspacing="0" cellpadding="0" align="center"><tbody><tr><td align="center"><table border="0" width="270" cellspacing="0" cellpadding="0" align="center"><tbody><tr><td style="border-collapse: collapse; word-break: break-word; word-wrap: break-word;" align="center"><a style="display: block; font-family: Arial, Helvetica, sans-serif; font-size: 16px; letter-spacing: 1px; color: #ffffff; line-height: 20px; text-decoration: none; text-align: center; background-color: #000; margin: 0 auto; width: 270px; box-sizing: border-box; padding: 8px 8px 8px 8px;" href="{{cart.link}}">CHECKOUT NOW</a></td></tr></tbody></table></td></tr></tbody></table></td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td style="font-size: 15px; line-height: 20px; text-align: center; color: #333032; padding: 0;" align="center" width="100%">For your assistance or if you would like to place an order directly with our customer service team, please call us at <?php echo "$admin_phone"; ?> </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr><tr><td style="line-height: 1px; font-size: 1px;" bgcolor="#cfcfcf" height="2"> </td></tr><tr><td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="30"> </td></tr></tbody></table></td><td class="td_w_sm" style="font-size: 0; line-height: 0;" width="30"> </td></tr></tbody></table></td></tr><tr><td><!-- ======= footer start======= --><table border="0" width="100%" cellspacing="0" cellpadding="0"><tbody><tr><td class="td_w_sm" style="font-size: 0; line-height: 0;" width="30"> </td><td style="padding: 0;"><table border="0" width="100%" cellspacing="0" cellpadding="0"><tbody>
144
 
145
+ <td style="font-size: 0pt; line-height: 0pt; text-align: left; padding: 0;" height="10"> </td></tr><tr><td style="font-size: 15px; line-height: 20px; text-align: center; color: #333032; padding: 0;" align="center" width="100%"><a href="{{cart.unsubscribe}}">Unsubscribe</a></td></tr></tbody></table><!-- ======= footer end======= --></td><td class="td_w_sm" style="font-size: 0; line-height: 0;" width="30"> </td></tr></tbody></table></td></tr></tbody></table></div><!-- [if mso | IE]> </td></tr></table> <![endif]--></td></tr></tbody></table>
includes/wcal-common.php CHANGED
@@ -932,8 +932,8 @@ class wcal_common {
932
  /**
933
  * Returns formatted price.
934
  *
935
- * @param float $price - Price to be formatted
936
- * @param string $currency - Currency.
937
  * @return string $price - Formatted price with currency symbol.
938
  * @since 5.6
939
  */
@@ -941,7 +941,7 @@ class wcal_common {
941
 
942
  if ( function_exists( 'icl_object_id' ) && isset( $currency ) && $currency !== '' ) {
943
  return wc_price( $price, array( 'currency' => $currency ) );
944
- }else{
945
  return wc_price( $price );
946
  }
947
  }
@@ -949,30 +949,65 @@ class wcal_common {
949
  /**
950
  * Returns the user role for registered users.
951
  *
952
- * @param int $uid - user ID.
953
  * @return array $roles - List of roles.
954
  * @since 5.6
955
  */
956
- public static function wcal_get_user_role( $uid ) {
957
  global $wpdb;
958
- $role = $wpdb->get_var("SELECT meta_value FROM {$wpdb->usermeta} WHERE meta_key = 'wp_capabilities' AND user_id = {$uid}");
959
-
960
- if( !$role ){
961
- return '';
962
- }
963
- $rarr = unserialize($role);
964
-
965
- $roles = is_array($rarr) ? array_keys( $rarr ) : array('non-user');
966
 
967
  /**
968
- * When store have the wpml it have so many user roles to fix the user role for admin we have applied this fix.
969
- */
970
- if ( in_array( 'administrator' , $roles) ){
971
-
972
  $roles[0] = 'administrator';
973
  }
974
 
975
- return ucfirst ( $roles[0] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
976
  }
977
  }
978
- ?>
932
  /**
933
  * Returns formatted price.
934
  *
935
+ * @param float $price - Price to be formatted
936
+ * @param string $currency - Currency.
937
  * @return string $price - Formatted price with currency symbol.
938
  * @since 5.6
939
  */
941
 
942
  if ( function_exists( 'icl_object_id' ) && isset( $currency ) && $currency !== '' ) {
943
  return wc_price( $price, array( 'currency' => $currency ) );
944
+ } else {
945
  return wc_price( $price );
946
  }
947
  }
949
  /**
950
  * Returns the user role for registered users.
951
  *
952
+ * @param int $uid - user ID.
953
  * @return array $roles - List of roles.
954
  * @since 5.6
955
  */
956
+ public static function wcal_get_user_role( $uid ) {
957
  global $wpdb;
958
+ $role = $wpdb->get_var( "SELECT meta_value FROM {$wpdb->usermeta} WHERE meta_key = 'wp_capabilities' AND user_id = {$uid}" );
959
+
960
+ if ( ! $role ) {
961
+ return '';
962
+ }
963
+ $rarr = unserialize( $role );
964
+
965
+ $roles = is_array( $rarr ) ? array_keys( $rarr ) : array( 'non-user' );
966
 
967
  /**
968
+ * When store have the wpml it have so many user roles to fix the user role for admin we have applied this fix.
969
+ */
970
+ if ( in_array( 'administrator', $roles ) ) {
971
+
972
  $roles[0] = 'administrator';
973
  }
974
 
975
+ return ucfirst( $roles[0] );
976
+ }
977
+
978
+ /**
979
+ * Return the template ID & Frequency of the last active email reminder.
980
+ *
981
+ * @return array Last Active email template ID & frequency.
982
+ * @since 5.8.2
983
+ */
984
+ public static function wcal_get_last_email_template() {
985
+ global $wpdb;
986
+ $get_active = $wpdb->get_results( // phpcs:ignore
987
+ "SELECT id, frequency, day_or_hour FROM `" . $wpdb->prefix . "ac_email_templates_lite` WHERE is_active = '1' ORDER BY `day_or_hour` DESC, `frequency` ASC" //phpcs:ignore
988
+ );
989
+ $hour_seconds = 3600; // 60 * 60
990
+ $day_seconds = 86400; // 24 * 60 * 60
991
+ $list_frequencies = array();
992
+ foreach ( $get_active as $active ) {
993
+ switch ( $active->day_or_hour ) {
994
+ case 'Days':
995
+ $template_freq = $active->frequency * $day_seconds;
996
+ break;
997
+ case 'Hours':
998
+ $template_freq = $active->frequency * $hour_seconds;
999
+ break;
1000
+ }
1001
+ $list_frequencies[ $active->id ] = (int) $template_freq;
1002
+ }
1003
+
1004
+ arsort( $list_frequencies, SORT_NUMERIC );
1005
+ reset( $list_frequencies );
1006
+ $template_id = key( $list_frequencies );
1007
+
1008
+ return array(
1009
+ $template_id => array_shift( $list_frequencies ),
1010
+ );
1011
  }
1012
  }
1013
+ ?>
includes/wcal_all_component.php CHANGED
@@ -1,18 +1,17 @@
1
  <?php
2
  /**
3
  * It will Add all the Boilerplate component when we activate the plugin.
 
4
  * @author Tyche Softwares
5
  * @package Abandoned-Cart-Lite-for-WooCommerce/Admin/Component
6
- *
7
  */
8
  if ( ! defined( 'ABSPATH' ) ) {
9
- exit; // Exit if accessed directly.
10
  }
11
 
12
  if ( ! class_exists( 'Wcal_All_Component' ) ) {
13
  /**
14
  * It will Add all the Boilerplate component when we activate the plugin.
15
- *
16
  */
17
  class Wcal_All_Component {
18
 
@@ -25,188 +24,214 @@ if ( ! class_exists( 'Wcal_All_Component' ) ) {
25
 
26
  if ( true === $is_admin ) {
27
 
28
- require_once( "component/woocommerce-check/ts-woo-active.php" );
29
 
30
- require_once( "component/tracking-data/ts-tracking.php" );
31
- require_once( "component/deactivate-survey-popup/class-ts-deactivation.php" );
32
 
33
- require_once( "component/welcome-page/ts-welcome.php" );
34
- require_once( "component/faq-support/ts-faq-support.php" );
35
- require_once( "component/pro-notices-in-lite/ts-pro-notices.php" );
36
 
37
- $wcal_plugin_name = 'Abandoned Cart Lite for WooCommerce';
38
- $wcal_locale = 'woocommerce-abandoned-cart';
39
- $wcal_file_name = 'woocommerce-abandoned-cart/woocommerce-ac.php';
40
- $wcal_plugin_prefix = 'wcal';
41
- $wcal_lite_plugin_prefix = 'wcal';
42
- $wcal_plugin_folder_name = 'woocommerce-abandoned-cart/';
43
- $wcal_plugin_dir_name = dirname ( untrailingslashit( plugin_dir_path ( __FILE__ ) ) ) . '/woocommerce-ac.php' ;
44
- $wcal_plugin_url = dirname ( untrailingslashit( plugins_url( '/', __FILE__ ) ) );
45
 
46
- $wcal_get_previous_version = get_option( 'wcal_previous_version' );
47
 
48
- $wcal_blog_post_link = 'https://www.tychesoftwares.com/abandoned-cart-lite-usage-tracking/';
49
 
50
- $wcal_plugins_page = 'admin.php?page=woocommerce_ac_page';
51
- $wcal_plugin_slug = 'woocommerce_ac_page';
52
- $wcal_pro_file_name = 'woocommerce-abandon-cart-pro/woocommerce-ac.php';
53
 
54
- $wcal_settings_page = 'admin.php?page=woocommerce_ac_page&action=emailsettings';
55
- $wcal_setting_add_on = 'woocommerce_ac_page';
56
- $wcal_setting_section = 'ac_lite_general_settings_section';
57
- $wcal_register_setting = 'woocommerce_ac_settings';
58
 
59
- new Wcal_TS_Woo_Active ( $wcal_plugin_name, $wcal_file_name, $wcal_locale );
60
 
61
- new Wcal_TS_tracking ( $wcal_plugin_prefix, $wcal_plugin_name, $wcal_blog_post_link, $wcal_locale, $wcal_plugin_url, $wcal_settings_page, $wcal_setting_add_on, $wcal_setting_section, $wcal_register_setting );
62
 
63
- new Wcal_TS_Tracker ( $wcal_plugin_prefix, $wcal_plugin_name );
64
 
65
- $wcal_deativate = new Wcal_TS_deactivate;
66
- $wcal_deativate->init ( $wcal_file_name, $wcal_plugin_name );
67
 
68
- /*new Wcal_TS_Welcome ( $wcal_plugin_name, $wcal_plugin_prefix, $wcal_locale, $wcal_plugin_folder_name, $wcal_plugin_dir_name, $wcal_get_previous_version );*/
69
 
70
- $ts_pro_faq = self::wcal_get_faq ();
71
- new Wcal_TS_Faq_Support( $wcal_plugin_name, $wcal_plugin_prefix, $wcal_plugins_page, $wcal_locale, $wcal_plugin_folder_name, $wcal_plugin_slug, $ts_pro_faq );
72
 
73
- /*$ts_pro_notices = self::wcal_get_notice_text ();
 
74
  new Wcal_ts_pro_notices( $wcal_plugin_name, $wcal_lite_plugin_prefix, $wcal_plugin_prefix, $ts_pro_notices, $wcal_file_name, $wcal_pro_file_name );*/
75
 
76
- }
77
- }
78
-
79
- /**
80
- * It will Display the notices in the admin dashboard for the pro vesion of the plugin.
81
- * @return array $ts_pro_notices All text of the notices
82
- */
83
- public static function wcal_get_notice_text () {
84
- $ts_pro_notices = array();
85
-
86
- $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=first&utm_campaign=AbandonedCartLitePlugin';
87
- $wcal_pro_diff = 'https://www.tychesoftwares.com/differences-between-pro-and-lite-versions-of-abandoned-cart-for-woocommerce-plugin/';
88
- /* translators: %1$s Link to Differences article, %2$s link to pro version */
89
- $message_first = wp_kses_post( sprintf( __( 'Now that you are all set with the Lite version, you can upgrade to Pro version to take your abandoned cart recovery to the next level. You can capture customer’s email address when they click Add to Cart, get access to 11 unique, fully responsive email templates, send text messages for recovery & <strong><a target="_blank" href= "%1$s">much more</a></strong>. <strong><a target="_blank" href= "%2$s">Purchase now</a></strong>.', 'woocommerce-abandoned-cart' ), $wcal_pro_diff, $wcal_ac_pro_link ) );
90
-
91
- $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=second&utm_campaign=AbandonedCartLitePlugin';
92
- /* translators: %s Link to Abandoned Cart Pro */
93
- $message_two = wp_kses_post( sprintf( __( 'Boost your sales by recovering up to 60% of the abandoned carts with our Abandoned Cart Pro for WooCommerce plugin. You can capture customer email addresses right when they click the Add To Cart button. <strong><a target="_blank" href= "%s"> Grab your copy of Abandon Cart Pro plugin now!</a></strong>', 'woocommerce-abandoned-cart' ), $wcal_ac_pro_link ) );
94
-
95
- $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=third&utm_campaign=AbandonedCartLitePlugin';
96
- /* translators: %s Link to Abandoned Cart Pro */
97
- $message_three = wp_kses_post( sprintf( __( 'Don\'t loose your sales to abandoned carts. Use our Abandon Cart Pro plugin & start recovering your lost sales in less then 60 seconds. <strong><a target="_blank" href= "%s">Grab it now!</a></strong>.', 'woocommerce-abandoned-cart' ), $wcal_ac_pro_link ) );
98
-
99
- $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=fourth&utm_campaign=AbandonedCartLitePlugin';
100
- /* translators: %s Link to Abandoned Cart Pro */
101
- $message_four = wp_kses_post( sprintf( __( 'Send Abandoned Cart reminders that actually convert. Take advantage of our fully responsive email templates designed specially with an intent to trigger conversion. <strong><a target="_blank" href= "%s">Purchase now</a></strong>.', 'woocommerce-abandoned-cart' ), $wcal_ac_pro_link ) );
102
-
103
- $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=fifth&utm_campaign=AbandonedCartLitePlugin';
104
- /* translators: %s Link to Abandoned Cart Pro */
105
- $message_five = wp_kses_post( sprintf( __( 'Increase your store sales by recovering your abandoned carts for just $119. No profit sharing, no monthly fees. Our Abandoned Cart Pro plugin comes with a 30 day money back guarantee as well. :) Use coupon code ACPRO20 & save $24!<br>
106
- <strong><a target="_blank" href= "%s">Grab your copy now!</a></strong>', 'woocommerce-abandoned-cart' ), $wcal_ac_pro_link ) );
107
-
108
- $_link = 'https://www.tychesoftwares.com/store/premium-plugins/order-delivery-date-for-woocommerce-pro-21/?utm_source=wpnotice&utm_medium=sixth&utm_campaign=AbandonedCartLitePlugin';
109
- /* translators: %s Link to Order Delivery Date Pro */
110
- $message_six = wp_kses_post( sprintf( __( 'Reduce cart abandonment rate by 57% with our Order Delivery Date Pro WooCommerce plugin. You can Create Delivery Settings by Shipping Zones & Shipping Classes. <br>Use discount code "ORDPRO20" and grab 20% discount on the purchase of the plugin. The discount code is valid only for the first 20 customers. <strong><a target="_blank" href= "%s">Purchase now</a></strong>', 'woocommerce-abandoned-cart' ), $_link ) );
111
-
112
- $_link = 'https://www.tychesoftwares.com/store/premium-plugins/product-delivery-date-pro-for-woocommerce/?utm_source=wpnotice&utm_medium=seventh&utm_campaign=AbandonedCartLitePlugin';
113
- /* translators: %s Link to Order Delivery Date Pro */
114
- $message_seven = wp_kses_post( sprintf( __( 'Allow your customers to select the Delivery Date on Single Product Page using our Product Delivery Date pro for WooCommerce Plugin. <br>
115
- <strong><a target="_blank" href= "%s">Shop now</a></strong> & be one of the 20 customers to get 20% discount on the plugin price. Use the code "PRDPRO20". Hurry!!', 'woocommerce-abandoned-cart' ), $_link ) );
116
-
117
- $_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-booking-plugin/?utm_source=wpnotice&utm_medium=eight&utm_campaign=AbandonedCartLitePlugin';
118
- /* translators: %s Link to WooCommerce Booking Plugin */
119
- $message_eight = wp_kses_post( sprintf( __( 'Allow your customers to book an appointment or rent an apartment with our Booking and Appointment for WooCommerce plugin. You can also sell your product as a resource or integrate with a few Vendor plugins. <br>Shop now & Save 20% on the plugin with the code "BKAP20". Only for first 20 customers. <strong><a target="_blank" href= "%s">Have it now!</a></strong>', 'woocommerce-abandoned-cart' ), $_link ) );
120
-
121
- $_link = 'https://www.tychesoftwares.com/store/premium-plugins/deposits-for-woocommerce/?utm_source=wpnotice&utm_medium=eight&utm_campaign=AbandonedCartLitePlugin';
122
- /* translators: %s Link to Deposits for WooCommerce */
123
- $message_nine = wp_kses_post( sprintf( __( ' Allow your customers to pay deposits on products using our Deposits for WooCommerce plugin. <br>
124
- <strong><a target="_blank" href= "%s">Purchase now</a></strong> & Grab 20% discount with the code "DFWP20". The discount code is valid only for the first 20 customers.', 'woocommerce-abandoned-cart' ), $_link ) );
125
-
126
- $ts_pro_notices = array (
127
- 1 => $message_first,
128
- 2 => $message_two,
129
- 3 => $message_three,
130
- 4 => $message_four,
131
- 5 => $message_five,
132
- 6 => $message_six,
133
- 7 => $message_seven,
134
- 8 => $message_eight,
135
- 9 => $message_nine,
136
- ) ;
137
-
138
- return $ts_pro_notices;
139
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  /**
142
- * It will contain all the FAQ which need to be display on the FAQ page.
143
- * @return array $ts_faq All questions and answers.
144
- *
145
- */
146
- public static function wcal_get_faq () {
147
-
148
- $ts_faq = array ();
149
-
150
- $ts_faq = array(
151
- 1 => array (
152
- 'question' => 'Why abandoned cart reminder emails are not being sent?',
153
- 'answer' => 'Please ensure you have at least one Email template "Active". As only active email templates are sent to recover the abandoned carts.
154
  <br/><br/>
155
- For sending the abandoned cart notification emails automatically, we use WP-Cron. If you have Email templates activated and still notification are not sent, then you can debug the issue by following this <a href = "https://www.tychesoftwares.com/docs/docs/abandoned-cart-pro-for-woocommerce/wp_alternate_cron/?utm_source=userwebsite&utm_medium=link&utm_campaign=AbandonedCartProFAQTab" target="_blank" >post</a>.'
156
- ),
157
- 2 => array (
158
- 'question' => 'How is the email address of the customers captured?',
159
- 'answer' => 'Our plugin captures visitor emails in real-time as they are typing it in to the email address field on the checkout page, so you don\'t need to worry about them changing their mind at the last second.
160
  <br/><br/>
161
- When logged-in user add the product to the cart we capture the email address from the user’s profile.'
162
- ),
163
- 3 => array (
164
- 'question' => 'I want to know if it is possible to exclude tax from product price for abandoned order.',
165
- 'answer' => 'Currently it is not possible to exclude tax from the product price from the abandoned order view if tax is applicable for the product.'
166
- ),
167
- 4 => array (
168
- 'question' => 'Is it possible to delete thousands of or all abandoned cart records at a once?',
169
- 'answer' => 'No, it is not possible to delete thousands of abandoned cart records in bulk. Our plugin does have the Bulk action functionality. But you can delete upto 30 Abandoned Carts in bulk. You can run a SQL query in the Database to delete those carts. For detailed steps please contact us via Support.'
170
- ),
171
- 5 => array (
172
- 'question' => 'Is there any way to not capture the visitors carts?',
173
- 'answer' => 'You can uncheck the “Start tracking from Cart Page” setting under the General Settings menu of the Settings tab.'
174
- ),
175
- 6 => array (
176
- 'question' => 'How can I know that abandoned cart reminders are being sent to customers?',
177
- 'answer' => 'It is not possible in the Abandoned Cart LITE plugin to check the records of the Abandoned Cart Reminder email whether email notifications are being sent or not. However you can upgrade to PRO version of our plugin to enable this feature.'
178
- ),
179
- 7 => array (
180
- 'question' => 'Is there an alternate way to send the abandon cart emails automatically at regular intervals? As the WP-Cron is not running on my site.',
181
- 'answer' => 'Yes, you can setup a manual cron in your server’s administration panel.
182
  <br/><br/>
183
  For example, if you are using cPanel, it has a section Named as "Cron Jobs" which allows you to create the cron job.
184
  <br/><br/>
185
  /usr/bin/wget -q -c {your_site_path}/wp-content/plugins/woocommerce-abandoned-cart/cron/wcal_send_email.php
186
  <br/><br/>
187
- You can refer to this document for creating a <a href="https://documentation.cpanel.net/display/68Docs/Cron+Jobs">cron job</a> in cPanel.'
188
- ),
189
  8 => array(
190
  'question' => 'Does the plugin consider the cart as abandoned for Pending and Failed order status?',
191
  'answer' => 'No, our plugin does not consider such carts (Pending Payment and Failed orders) as abandoned. It will not send the abandoned cart reminder email to the customers if they fail to proceed with the payment.',
192
  ),
193
- 9 => array (
194
- 'question' => 'How can we translate the strings of {{products.cart}} merge tag in the email?',
195
- 'answer' => 'To translate the strings, you need to generate ".po" and ".mo" files in your respective language. These files then need to be added to the following path: "woocommerce-abandoned-cart/i18n/languages"'
196
- ),
197
- 10 => array (
198
- 'question' => 'There was a problem creating an email template on Multisite.',
199
- 'answer' => 'On Multisite, if you have activated the plugin from Network site then please deactivate it and activate the Abandoned Cart Lite plugin from an Individual site. So, one default email template will be created on the activation of the plugin and you can create new email template.'
200
- ),
201
- 11 => array(
202
- 'question' => 'Abnormal amount of carts are being logged by the plugin.',
203
- 'answer' => "This might be due to a bot executing 'Add to Cart' urls on the site. Adding a few lines in the robots.txt file can stop the bots from actually adding products to the cart.
204
- Please follow the instructions mentioned <a href='https://www.tychesoftwares.com/docs/docs/abandoned-cart-for-woocommerce-lite/track-only-genuine-visitor-carts/' target='_blank'>here.</a>"
205
- )
206
- );
207
-
208
- return $ts_faq;
209
- }
210
  }
211
  $Wcal_All_Component = new Wcal_All_Component();
212
  }
1
  <?php
2
  /**
3
  * It will Add all the Boilerplate component when we activate the plugin.
4
+ *
5
  * @author Tyche Softwares
6
  * @package Abandoned-Cart-Lite-for-WooCommerce/Admin/Component
 
7
  */
8
  if ( ! defined( 'ABSPATH' ) ) {
9
+ exit; // Exit if accessed directly.
10
  }
11
 
12
  if ( ! class_exists( 'Wcal_All_Component' ) ) {
13
  /**
14
  * It will Add all the Boilerplate component when we activate the plugin.
 
15
  */
16
  class Wcal_All_Component {
17
 
24
 
25
  if ( true === $is_admin ) {
26
 
27
+ require_once 'component/woocommerce-check/ts-woo-active.php';
28
 
29
+ require_once 'component/tracking-data/ts-tracking.php';
30
+ require_once 'component/deactivate-survey-popup/class-ts-deactivation.php';
31
 
32
+ require_once 'component/welcome-page/ts-welcome.php';
33
+ require_once 'component/faq-support/ts-faq-support.php';
34
+ require_once 'component/pro-notices-in-lite/ts-pro-notices.php';
35
 
36
+ $wcal_plugin_name = 'Abandoned Cart Lite for WooCommerce';
37
+ $wcal_locale = 'woocommerce-abandoned-cart';
38
+ $wcal_file_name = 'woocommerce-abandoned-cart/woocommerce-ac.php';
39
+ $wcal_plugin_prefix = 'wcal';
40
+ $wcal_lite_plugin_prefix = 'wcal';
41
+ $wcal_plugin_folder_name = 'woocommerce-abandoned-cart/';
42
+ $wcal_plugin_dir_name = dirname( untrailingslashit( plugin_dir_path( __FILE__ ) ) ) . '/woocommerce-ac.php';
43
+ $wcal_plugin_url = dirname( untrailingslashit( plugins_url( '/', __FILE__ ) ) );
44
 
45
+ $wcal_get_previous_version = get_option( 'wcal_previous_version' );
46
 
47
+ $wcal_blog_post_link = 'https://www.tychesoftwares.com/abandoned-cart-lite-usage-tracking/';
48
 
49
+ $wcal_plugins_page = 'admin.php?page=woocommerce_ac_page';
50
+ $wcal_plugin_slug = 'woocommerce_ac_page';
51
+ $wcal_pro_file_name = 'woocommerce-abandon-cart-pro/woocommerce-ac.php';
52
 
53
+ $wcal_settings_page = 'admin.php?page=woocommerce_ac_page&action=emailsettings';
54
+ $wcal_setting_add_on = 'woocommerce_ac_page';
55
+ $wcal_setting_section = 'ac_lite_general_settings_section';
56
+ $wcal_register_setting = 'woocommerce_ac_settings';
57
 
58
+ new Wcal_TS_Woo_Active( $wcal_plugin_name, $wcal_file_name, $wcal_locale );
59
 
60
+ new Wcal_TS_tracking( $wcal_plugin_prefix, $wcal_plugin_name, $wcal_blog_post_link, $wcal_locale, $wcal_plugin_url, $wcal_settings_page, $wcal_setting_add_on, $wcal_setting_section, $wcal_register_setting );
61
 
62
+ new Wcal_TS_Tracker( $wcal_plugin_prefix, $wcal_plugin_name );
63
 
64
+ $wcal_deativate = new Wcal_TS_deactivate();
65
+ $wcal_deativate->init( $wcal_file_name, $wcal_plugin_name );
66
 
67
+ /*new Wcal_TS_Welcome ( $wcal_plugin_name, $wcal_plugin_prefix, $wcal_locale, $wcal_plugin_folder_name, $wcal_plugin_dir_name, $wcal_get_previous_version );*/
68
 
69
+ $ts_pro_faq = self::wcal_get_faq();
70
+ new Wcal_TS_Faq_Support( $wcal_plugin_name, $wcal_plugin_prefix, $wcal_plugins_page, $wcal_locale, $wcal_plugin_folder_name, $wcal_plugin_slug, $ts_pro_faq );
71
 
72
+ /*
73
+ $ts_pro_notices = self::wcal_get_notice_text ();
74
  new Wcal_ts_pro_notices( $wcal_plugin_name, $wcal_lite_plugin_prefix, $wcal_plugin_prefix, $ts_pro_notices, $wcal_file_name, $wcal_pro_file_name );*/
75
 
76
+ }
77
+ }
78
+
79
+ /**
80
+ * It will Display the notices in the admin dashboard for the pro vesion of the plugin.
81
+ *
82
+ * @return array $ts_pro_notices All text of the notices
83
+ */
84
+ public static function wcal_get_notice_text() {
85
+ $ts_pro_notices = array();
86
+
87
+ $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=first&utm_campaign=AbandonedCartLitePlugin';
88
+ $wcal_pro_diff = 'https://www.tychesoftwares.com/differences-between-pro-and-lite-versions-of-abandoned-cart-for-woocommerce-plugin/';
89
+ /* translators: %1$s Link to Differences article, %2$s link to pro version */
90
+ $message_first = wp_kses_post( sprintf( __( 'Now that you are all set with the Lite version, you can upgrade to Pro version to take your abandoned cart recovery to the next level. You can capture customer’s email address when they click Add to Cart, get access to 11 unique, fully responsive email templates, send text messages for recovery & <strong><a target="_blank" href= "%1$s">much more</a></strong>. <strong><a target="_blank" href= "%2$s">Purchase now</a></strong>.', 'woocommerce-abandoned-cart' ), $wcal_pro_diff, $wcal_ac_pro_link ) );
91
+
92
+ $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=second&utm_campaign=AbandonedCartLitePlugin';
93
+ /* translators: %s Link to Abandoned Cart Pro */
94
+ $message_two = wp_kses_post( sprintf( __( 'Boost your sales by recovering up to 60% of the abandoned carts with our Abandoned Cart Pro for WooCommerce plugin. You can capture customer email addresses right when they click the Add To Cart button. <strong><a target="_blank" href= "%s"> Grab your copy of Abandon Cart Pro plugin now!</a></strong>', 'woocommerce-abandoned-cart' ), $wcal_ac_pro_link ) );
95
+
96
+ $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=third&utm_campaign=AbandonedCartLitePlugin';
97
+ /* translators: %s Link to Abandoned Cart Pro */
98
+ $message_three = wp_kses_post( sprintf( __( 'Don\'t loose your sales to abandoned carts. Use our Abandon Cart Pro plugin & start recovering your lost sales in less then 60 seconds. <strong><a target="_blank" href= "%s">Grab it now!</a></strong>.', 'woocommerce-abandoned-cart' ), $wcal_ac_pro_link ) );
99
+
100
+ $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=fourth&utm_campaign=AbandonedCartLitePlugin';
101
+ /* translators: %s Link to Abandoned Cart Pro */
102
+ $message_four = wp_kses_post( sprintf( __( 'Send Abandoned Cart reminders that actually convert. Take advantage of our fully responsive email templates designed specially with an intent to trigger conversion. <strong><a target="_blank" href= "%s">Purchase now</a></strong>.', 'woocommerce-abandoned-cart' ), $wcal_ac_pro_link ) );
103
+
104
+ $wcal_ac_pro_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro/?utm_source=wpnotice&utm_medium=fifth&utm_campaign=AbandonedCartLitePlugin';
105
+ /* translators: %s Link to Abandoned Cart Pro */
106
+ $message_five = wp_kses_post(
107
+ sprintf(
108
+ __(
109
+ 'Increase your store sales by recovering your abandoned carts for just $119. No profit sharing, no monthly fees. Our Abandoned Cart Pro plugin comes with a 30 day money back guarantee as well. :) Use coupon code ACPRO20 & save $24!<br>
110
+ <strong><a target="_blank" href= "%s">Grab your copy now!</a></strong>',
111
+ 'woocommerce-abandoned-cart'
112
+ ),
113
+ $wcal_ac_pro_link
114
+ )
115
+ );
116
+
117
+ $_link = 'https://www.tychesoftwares.com/store/premium-plugins/order-delivery-date-for-woocommerce-pro-21/?utm_source=wpnotice&utm_medium=sixth&utm_campaign=AbandonedCartLitePlugin';
118
+ /* translators: %s Link to Order Delivery Date Pro */
119
+ $message_six = wp_kses_post( sprintf( __( 'Reduce cart abandonment rate by 57% with our Order Delivery Date Pro WooCommerce plugin. You can Create Delivery Settings by Shipping Zones & Shipping Classes. <br>Use discount code "ORDPRO20" and grab 20% discount on the purchase of the plugin. The discount code is valid only for the first 20 customers. <strong><a target="_blank" href= "%s">Purchase now</a></strong>', 'woocommerce-abandoned-cart' ), $_link ) );
120
+
121
+ $_link = 'https://www.tychesoftwares.com/store/premium-plugins/product-delivery-date-pro-for-woocommerce/?utm_source=wpnotice&utm_medium=seventh&utm_campaign=AbandonedCartLitePlugin';
122
+ /* translators: %s Link to Order Delivery Date Pro */
123
+ $message_seven = wp_kses_post(
124
+ sprintf(
125
+ __(
126
+ 'Allow your customers to select the Delivery Date on Single Product Page using our Product Delivery Date pro for WooCommerce Plugin. <br>
127
+ <strong><a target="_blank" href= "%s">Shop now</a></strong> & be one of the 20 customers to get 20% discount on the plugin price. Use the code "PRDPRO20". Hurry!!',
128
+ 'woocommerce-abandoned-cart'
129
+ ),
130
+ $_link
131
+ )
132
+ );
133
+
134
+ $_link = 'https://www.tychesoftwares.com/store/premium-plugins/woocommerce-booking-plugin/?utm_source=wpnotice&utm_medium=eight&utm_campaign=AbandonedCartLitePlugin';
135
+ /* translators: %s Link to WooCommerce Booking Plugin */
136
+ $message_eight = wp_kses_post( sprintf( __( 'Allow your customers to book an appointment or rent an apartment with our Booking and Appointment for WooCommerce plugin. You can also sell your product as a resource or integrate with a few Vendor plugins. <br>Shop now & Save 20% on the plugin with the code "BKAP20". Only for first 20 customers. <strong><a target="_blank" href= "%s">Have it now!</a></strong>', 'woocommerce-abandoned-cart' ), $_link ) );
137
+
138
+ $_link = 'https://www.tychesoftwares.com/store/premium-plugins/deposits-for-woocommerce/?utm_source=wpnotice&utm_medium=eight&utm_campaign=AbandonedCartLitePlugin';
139
+ /* translators: %s Link to Deposits for WooCommerce */
140
+ $message_nine = wp_kses_post(
141
+ sprintf(
142
+ __(
143
+ ' Allow your customers to pay deposits on products using our Deposits for WooCommerce plugin. <br>
144
+ <strong><a target="_blank" href= "%s">Purchase now</a></strong> & Grab 20% discount with the code "DFWP20". The discount code is valid only for the first 20 customers.',
145
+ 'woocommerce-abandoned-cart'
146
+ ),
147
+ $_link
148
+ )
149
+ );
150
+
151
+ $ts_pro_notices = array(
152
+ 1 => $message_first,
153
+ 2 => $message_two,
154
+ 3 => $message_three,
155
+ 4 => $message_four,
156
+ 5 => $message_five,
157
+ 6 => $message_six,
158
+ 7 => $message_seven,
159
+ 8 => $message_eight,
160
+ 9 => $message_nine,
161
+ );
162
+
163
+ return $ts_pro_notices;
164
+ }
165
 
166
  /**
167
+ * It will contain all the FAQ which need to be display on the FAQ page.
168
+ *
169
+ * @return array $ts_faq All questions and answers.
170
+ */
171
+ public static function wcal_get_faq() {
172
+
173
+ $ts_faq = array();
174
+
175
+ $ts_faq = array(
176
+ 1 => array(
177
+ 'question' => 'Why abandoned cart reminder emails are not being sent?',
178
+ 'answer' => 'Please ensure you have at least one Email template "Active". As only active email templates are sent to recover the abandoned carts.
179
  <br/><br/>
180
+ For sending the abandoned cart notification emails automatically, we use WP-Cron. If you have Email templates activated and still notification are not sent, then you can debug the issue by following this <a href = "https://www.tychesoftwares.com/docs/docs/abandoned-cart-pro-for-woocommerce/wp_alternate_cron/?utm_source=userwebsite&utm_medium=link&utm_campaign=AbandonedCartProFAQTab" target="_blank" >post</a>.',
181
+ ),
182
+ 2 => array(
183
+ 'question' => 'How is the email address of the customers captured?',
184
+ 'answer' => 'Our plugin captures visitor emails in real-time as they are typing it in to the email address field on the checkout page, so you don\'t need to worry about them changing their mind at the last second.
185
  <br/><br/>
186
+ When logged-in user add the product to the cart we capture the email address from the user’s profile.',
187
+ ),
188
+ 3 => array(
189
+ 'question' => 'I want to know if it is possible to exclude tax from product price for abandoned order.',
190
+ 'answer' => 'Currently it is not possible to exclude tax from the product price from the abandoned order view if tax is applicable for the product.',
191
+ ),
192
+ 4 => array(
193
+ 'question' => 'Is it possible to delete thousands of or all abandoned cart records at a once?',
194
+ 'answer' => 'No, it is not possible to delete thousands of abandoned cart records in bulk. Our plugin does have the Bulk action functionality. But you can delete upto 30 Abandoned Carts in bulk. You can run a SQL query in the Database to delete those carts. For detailed steps please contact us via Support.',
195
+ ),
196
+ 5 => array(
197
+ 'question' => 'Is there any way to not capture the visitors carts?',
198
+ 'answer' => 'You can uncheck the “Start tracking from Cart Page” setting under the General Settings menu of the Settings tab.',
199
+ ),
200
+ 6 => array(
201
+ 'question' => 'How can I know that abandoned cart reminders are being sent to customers?',
202
+ 'answer' => 'It is not possible in the Abandoned Cart LITE plugin to check the records of the Abandoned Cart Reminder email whether email notifications are being sent or not. However you can upgrade to PRO version of our plugin to enable this feature.',
203
+ ),
204
+ 7 => array(
205
+ 'question' => 'Is there an alternate way to send the abandon cart emails automatically at regular intervals? As the WP-Cron is not running on my site.',
206
+ 'answer' => 'Yes, you can setup a manual cron in your server’s administration panel.
207
  <br/><br/>
208
  For example, if you are using cPanel, it has a section Named as "Cron Jobs" which allows you to create the cron job.
209
  <br/><br/>
210
  /usr/bin/wget -q -c {your_site_path}/wp-content/plugins/woocommerce-abandoned-cart/cron/wcal_send_email.php
211
  <br/><br/>
212
+ You can refer to this document for creating a <a href="https://documentation.cpanel.net/display/68Docs/Cron+Jobs">cron job</a> in cPanel.',
213
+ ),
214
  8 => array(
215
  'question' => 'Does the plugin consider the cart as abandoned for Pending and Failed order status?',
216
  'answer' => 'No, our plugin does not consider such carts (Pending Payment and Failed orders) as abandoned. It will not send the abandoned cart reminder email to the customers if they fail to proceed with the payment.',
217
  ),
218
+ 9 => array(
219
+ 'question' => 'How can we translate the strings of {{products.cart}} merge tag in the email?',
220
+ 'answer' => 'To translate the strings, you need to generate ".po" and ".mo" files in your respective language. These files then need to be added to the following path: "woocommerce-abandoned-cart/i18n/languages"',
221
+ ),
222
+ 10 => array(
223
+ 'question' => 'There was a problem creating an email template on Multisite.',
224
+ 'answer' => 'On Multisite, if you have activated the plugin from Network site then please deactivate it and activate the Abandoned Cart Lite plugin from an Individual site. So, one default email template will be created on the activation of the plugin and you can create new email template.',
225
+ ),
226
+ 11 => array(
227
+ 'question' => 'Abnormal amount of carts are being logged by the plugin.',
228
+ 'answer' => "This might be due to a bot executing 'Add to Cart' urls on the site. Adding a few lines in the robots.txt file can stop the bots from actually adding products to the cart.
229
+ Please follow the instructions mentioned <a href='https://www.tychesoftwares.com/docs/docs/abandoned-cart-for-woocommerce-lite/track-only-genuine-visitor-carts/' target='_blank'>here.</a>",
230
+ ),
231
+ );
232
+
233
+ return $ts_faq;
234
+ }
235
  }
236
  $Wcal_All_Component = new Wcal_All_Component();
237
  }
includes/wcal_class-guest.php CHANGED
@@ -50,9 +50,9 @@ if ( ! class_exists( 'woocommerce_guest_ac' ) ) {
50
  */
51
  function user_side_js() {
52
 
53
- if( ! is_user_logged_in() ) {
54
  wp_nonce_field( 'save_data', 'wcal_guest_capture_nonce' );
55
-
56
  wp_enqueue_script(
57
  'wcal_guest_capture',
58
  plugins_url( '../assets/js/wcal_guest_capture.min.js', __FILE__ ),
@@ -98,10 +98,10 @@ if ( ! class_exists( 'woocommerce_guest_ac' ) ) {
98
  function save_data() {
99
  if ( ! is_user_logged_in() ) {
100
 
101
- if( ! isset( $_POST[ 'wcal_guest_capture_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wcal_guest_capture_nonce'], 'save_data' ) ) {
102
  die();
103
  }
104
-
105
  global $wpdb, $woocommerce;
106
  if ( isset( $_POST['billing_first_name'] ) && '' !== $_POST['billing_first_name'] ) {
107
  wcal_common::wcal_set_cart_session( 'billing_first_name', sanitize_text_field( wp_unslash( $_POST['billing_first_name'] ) ) );
@@ -113,82 +113,89 @@ if ( ! class_exists( 'woocommerce_guest_ac' ) ) {
113
  wcal_common::wcal_set_cart_session( 'billing_company', sanitize_text_field( wp_unslash( $_POST['billing_company'] ) ) );
114
  }
115
  if ( isset( $_POST['billing_address_1'] ) && $_POST['billing_address_1'] != '' ) {
116
- wcal_common::wcal_set_cart_session( 'billing_address_1', sanitize_text_field( $_POST['billing_address_1'] ) );
117
  }
118
  if ( isset( $_POST['billing_address_2'] ) && $_POST['billing_address_2'] != '' ) {
119
- wcal_common::wcal_set_cart_session( 'billing_address_2', sanitize_text_field( $_POST['billing_address_2'] ) );
120
  }
121
  if ( isset( $_POST['billing_city'] ) && $_POST['billing_city'] != '' ) {
122
- wcal_common::wcal_set_cart_session( 'billing_city', sanitize_text_field( $_POST['billing_city'] ) );
123
  }
124
  if ( isset( $_POST['billing_state'] ) && $_POST['billing_state'] != '' ) {
125
- wcal_common::wcal_set_cart_session( 'billing_state', sanitize_text_field( $_POST['billing_state'] ) );
126
  }
127
  if ( isset( $_POST['billing_postcode'] ) && $_POST['billing_postcode'] != '' ) {
128
- wcal_common::wcal_set_cart_session( 'billing_postcode', sanitize_text_field( $_POST['billing_postcode'] ) );
129
  }
130
  if ( isset( $_POST['billing_country'] ) && $_POST['billing_country'] != '' ) {
131
- wcal_common::wcal_set_cart_session( 'billing_country', sanitize_text_field( $_POST['billing_country'] ) );
132
  }
133
  if ( isset( $_POST['billing_email'] ) && $_POST['billing_email'] != '' ) {
134
- wcal_common::wcal_set_cart_session( 'billing_email', sanitize_text_field( $_POST['billing_email'] ) );
135
  }
136
  if ( isset( $_POST['billing_phone'] ) && $_POST['billing_phone'] != '' ) {
137
- wcal_common::wcal_set_cart_session( 'billing_phone', sanitize_text_field( $_POST['billing_phone'] ) );
138
  }
139
  if ( isset( $_POST['order_notes'] ) && $_POST['order_notes'] != '' ) {
140
- wcal_common::wcal_set_cart_session( 'order_notes', sanitize_text_field( $_POST['order_notes'] ) );
141
  }
142
  if ( isset( $_POST['ship_to_billing'] ) && $_POST['ship_to_billing'] != '' ) {
143
- wcal_common::wcal_set_cart_session( 'ship_to_billing', sanitize_text_field( $_POST['ship_to_billing'] ) );
144
  }
145
  if ( isset( $_POST['shipping_first_name'] ) && $_POST['shipping_first_name'] != '' ) {
146
- wcal_common::wcal_set_cart_session( 'shipping_first_name', sanitize_text_field( $_POST['shipping_first_name'] ) );
147
  }
148
  if ( isset( $_POST['shipping_last_name'] ) && $_POST['shipping_last_name'] != '' ) {
149
- wcal_common::wcal_set_cart_session( 'shipping_last_name', sanitize_text_field( $_POST['shipping_last_name'] ) );
150
  }
151
  if ( isset( $_POST['shipping_company'] ) && $_POST['shipping_company'] != '' ) {
152
- wcal_common::wcal_set_cart_session( 'shipping_company', sanitize_text_field( $_POST['shipping_company'] ) );
153
  }
154
  if ( isset( $_POST['shipping_address_1'] ) && $_POST['shipping_address_1'] != '' ) {
155
- wcal_common::wcal_set_cart_session( 'shipping_address_1', sanitize_text_field( $_POST['shipping_address_1'] ) );
156
  }
157
  if ( isset( $_POST['shipping_address_2'] ) && $_POST['shipping_address_2'] != '' ) {
158
- wcal_common::wcal_set_cart_session( 'shipping_address_2', sanitize_text_field( $_POST['shipping_address_2'] ) );
159
  }
160
  if ( isset( $_POST['shipping_city'] ) && $_POST['shipping_city'] != '' ) {
161
- wcal_common::wcal_set_cart_session( 'shipping_city', sanitize_text_field( $_POST['shipping_city'] ) );
162
  }
163
  if ( isset( $_POST['shipping_state'] ) && $_POST['shipping_state'] != '' ) {
164
- wcal_common::wcal_set_cart_session( 'shipping_state', sanitize_text_field( $_POST['shipping_state'] ) );
165
  }
166
  if ( isset( $_POST['shipping_postcode'] ) && $_POST['shipping_postcode'] != '' ) {
167
- wcal_common::wcal_set_cart_session( 'shipping_postcode', sanitize_text_field( $_POST['shipping_postcode'] ) );
168
  }
169
  if ( isset( $_POST['shipping_country'] ) && $_POST['shipping_country'] != '' ) {
170
- wcal_common::wcal_set_cart_session( 'shipping_country', sanitize_text_field( $_POST['shipping_country'] ) );
171
  }
172
  // If a record is present in the guest cart history table for the same email id, then delete the previous records
173
- $query_guest = 'SELECT id FROM `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite`
174
- WHERE email_id = %s';
175
- $results_guest = $wpdb->get_results( $wpdb->prepare( $query_guest, wcal_common::wcal_get_cart_session( 'billing_email' ) ) );
 
 
 
176
 
177
  if ( $results_guest ) {
178
  foreach ( $results_guest as $key => $value ) {
179
  $result = $wpdb->get_results(
180
  $wpdb->prepare(
181
- 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite`
182
- WHERE user_id = %d AND recovered_cart = "0"',
183
- $value->id
184
  )
185
  );
186
  // update existing record and create new record if guest cart history table will have the same email id.
187
 
188
  if ( count( $result ) ) {
189
- $update_mobile_info = 'UPDATE `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE user_id = '" . $value->id . "'";
190
- $wpdb->query( $update_mobile_info );
191
-
 
 
 
 
192
  }
193
  }
194
  }
@@ -205,9 +212,17 @@ if ( ! class_exists( 'woocommerce_guest_ac' ) ) {
205
  $shipping_zipcode = $billing_zipcode = wcal_common::wcal_get_cart_session( 'billing_postcode' );
206
  }
207
  $shipping_charges = $woocommerce->cart->shipping_total;
208
- $insert_guest = 'INSERT INTO `' . $wpdb->prefix . "ac_guest_abandoned_cart_history_lite`( billing_first_name, billing_last_name, email_id, billing_zipcode, shipping_zipcode, shipping_charges )
209
- VALUES ( '" . $billing_first_name . "', '" . $billing_last_name . "', '" . wcal_common::wcal_get_cart_session( 'billing_email' ) . "', '" . $billing_zipcode . "', '" . $shipping_zipcode . "', '" . $shipping_charges . "' )";
210
- $wpdb->query( $insert_guest );
 
 
 
 
 
 
 
 
211
 
212
  // Insert record in abandoned cart table for the guest user
213
  $user_id = $wpdb->insert_id;
@@ -217,9 +232,15 @@ if ( ! class_exists( 'woocommerce_guest_ac' ) ) {
217
  $cart_cut_off_time = $cut_off_time * 60;
218
  $compare_time = $current_time - $cart_cut_off_time;
219
 
220
- $query = 'SELECT * FROM `' . $wpdb->prefix . "ac_abandoned_cart_history_lite`
221
- WHERE user_id = %d AND cart_ignored = '0' AND recovered_cart = '0' AND user_type = 'GUEST'";
222
- $results = $wpdb->get_results( $wpdb->prepare( $query, $user_id ) );
 
 
 
 
 
 
223
 
224
  $cart = array();
225
 
@@ -231,16 +252,30 @@ if ( ! class_exists( 'woocommerce_guest_ac' ) ) {
231
 
232
  if ( 0 == count( $results ) ) {
233
  $get_cookie = WC()->session->get_session_cookie();
234
- $cart_info = addslashes( json_encode( $cart ) );
235
-
236
- $query = 'SELECT * FROM `' . $wpdb->prefix . "ac_abandoned_cart_history_lite`
237
- WHERE session_id LIKE %s AND cart_ignored = '0' AND recovered_cart = '0' ";
238
- $results = $wpdb->get_results( $wpdb->prepare( $query, $get_cookie[0] ) );
239
-
 
 
 
 
 
240
  if ( 0 == count( $results ) ) {
241
- $insert_query = 'INSERT INTO `' . $wpdb->prefix . "ac_abandoned_cart_history_lite`( user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, recovered_cart, user_type, session_id )
242
- VALUES ( '" . $user_id . "', '" . $cart_info . "', '" . $current_time . "', '0', '0', 'GUEST', '" . $get_cookie[0] . "' )";
243
- $wpdb->query( $insert_query );
 
 
 
 
 
 
 
 
 
244
 
245
  $abandoned_cart_id = $wpdb->insert_id;
246
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
@@ -251,41 +286,79 @@ if ( ! class_exists( 'woocommerce_guest_ac' ) ) {
251
  if ( is_multisite() ) {
252
  // get main site's table prefix
253
  $main_prefix = $wpdb->get_blog_prefix( 1 );
254
- $insert_persistent_cart = 'INSERT INTO `' . $main_prefix . "usermeta`( user_id, meta_key, meta_value )
255
- VALUES ( '" . $user_id . "', '_woocommerce_persistent_cart', '" . $cart_info . "' )";
256
- $wpdb->query( $insert_persistent_cart );
 
 
 
 
 
257
 
258
  } else {
259
- $insert_persistent_cart = 'INSERT INTO `' . $wpdb->prefix . "usermeta`( user_id, meta_key, meta_value )
260
- VALUES ( '" . $user_id . "', '_woocommerce_persistent_cart', '" . $cart_info . "' )";
261
- $wpdb->query( $insert_persistent_cart );
 
 
 
 
 
262
  }
263
  } else {
264
- $query_update = 'UPDATE `' . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET user_id = '" . $user_id . "', abandoned_cart_info = '" . $cart_info . "', abandoned_cart_time = '" . $current_time . "' WHERE session_id ='" . $get_cookie[0] . "' AND cart_ignored='0' ";
265
- $wpdb->query( $query_update );
266
- $query_update_get = 'SELECT * FROM `' . $wpdb->prefix . "ac_abandoned_cart_history_lite`
267
- WHERE user_id ='" . $user_id . "' AND cart_ignored='0' AND session_id ='" . $get_cookie[0] . "' ";
268
- $get_abandoned_record = $wpdb->get_results( $query_update_get );
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  if ( count( $get_abandoned_record ) > 0 ) {
271
  $abandoned_cart_id = $get_abandoned_record[0]->id;
272
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
273
  }
274
 
275
- $insert_persistent_cart = 'INSERT INTO `' . $wpdb->prefix . "usermeta`( user_id, meta_key, meta_value )
276
- VALUES ( '" . $user_id . "', '_woocommerce_persistent_cart', '" . $cart_info . "' )";
277
- $wpdb->query( $insert_persistent_cart );
 
 
 
 
 
278
  if ( is_multisite() ) {
279
  // get main site's table prefix
280
  $main_prefix = $wpdb->get_blog_prefix( 1 );
281
- $insert_persistent_cart = 'INSERT INTO `' . $main_prefix . "usermeta`( user_id, meta_key, meta_value )
282
- VALUES ( '" . $user_id . "', '_woocommerce_persistent_cart', '" . $cart_info . "' )";
283
- $wpdb->query( $insert_persistent_cart );
 
 
 
 
 
284
 
285
  } else {
286
- $insert_persistent_cart = 'INSERT INTO `' . $wpdb->prefix . "usermeta`( user_id, meta_key, meta_value )
287
- VALUES ( '" . $user_id . "', '_woocommerce_persistent_cart', '" . $cart_info . "' )";
288
- $wpdb->query( $insert_persistent_cart );
 
 
 
 
 
289
  }
290
  }
291
  }
50
  */
51
  function user_side_js() {
52
 
53
+ if ( ! is_user_logged_in() ) {
54
  wp_nonce_field( 'save_data', 'wcal_guest_capture_nonce' );
55
+
56
  wp_enqueue_script(
57
  'wcal_guest_capture',
58
  plugins_url( '../assets/js/wcal_guest_capture.min.js', __FILE__ ),
98
  function save_data() {
99
  if ( ! is_user_logged_in() ) {
100
 
101
+ if ( ! isset( $_POST['wcal_guest_capture_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wcal_guest_capture_nonce'] ) ), 'save_data' ) ) {
102
  die();
103
  }
104
+
105
  global $wpdb, $woocommerce;
106
  if ( isset( $_POST['billing_first_name'] ) && '' !== $_POST['billing_first_name'] ) {
107
  wcal_common::wcal_set_cart_session( 'billing_first_name', sanitize_text_field( wp_unslash( $_POST['billing_first_name'] ) ) );
113
  wcal_common::wcal_set_cart_session( 'billing_company', sanitize_text_field( wp_unslash( $_POST['billing_company'] ) ) );
114
  }
115
  if ( isset( $_POST['billing_address_1'] ) && $_POST['billing_address_1'] != '' ) {
116
+ wcal_common::wcal_set_cart_session( 'billing_address_1', sanitize_text_field( wp_unslash( $_POST['billing_address_1'] ) ) );
117
  }
118
  if ( isset( $_POST['billing_address_2'] ) && $_POST['billing_address_2'] != '' ) {
119
+ wcal_common::wcal_set_cart_session( 'billing_address_2', sanitize_text_field( wp_unslash( $_POST['billing_address_2'] ) ) );
120
  }
121
  if ( isset( $_POST['billing_city'] ) && $_POST['billing_city'] != '' ) {
122
+ wcal_common::wcal_set_cart_session( 'billing_city', sanitize_text_field( wp_unslash( $_POST['billing_city'] ) ) );
123
  }
124
  if ( isset( $_POST['billing_state'] ) && $_POST['billing_state'] != '' ) {
125
+ wcal_common::wcal_set_cart_session( 'billing_state', sanitize_text_field( wp_unslash( $_POST['billing_state'] ) ) );
126
  }
127
  if ( isset( $_POST['billing_postcode'] ) && $_POST['billing_postcode'] != '' ) {
128
+ wcal_common::wcal_set_cart_session( 'billing_postcode', sanitize_text_field( wp_unslash( $_POST['billing_postcode'] ) ) );
129
  }
130
  if ( isset( $_POST['billing_country'] ) && $_POST['billing_country'] != '' ) {
131
+ wcal_common::wcal_set_cart_session( 'billing_country', sanitize_text_field( wp_unslash( $_POST['billing_country'] ) ) );
132
  }
133
  if ( isset( $_POST['billing_email'] ) && $_POST['billing_email'] != '' ) {
134
+ wcal_common::wcal_set_cart_session( 'billing_email', sanitize_text_field( wp_unslash( $_POST['billing_email'] ) ) );
135
  }
136
  if ( isset( $_POST['billing_phone'] ) && $_POST['billing_phone'] != '' ) {
137
+ wcal_common::wcal_set_cart_session( 'billing_phone', sanitize_text_field( wp_unslash( $_POST['billing_phone'] ) ) );
138
  }
139
  if ( isset( $_POST['order_notes'] ) && $_POST['order_notes'] != '' ) {
140
+ wcal_common::wcal_set_cart_session( 'order_notes', sanitize_text_field( wp_unslash( $_POST['order_notes'] ) ) );
141
  }
142
  if ( isset( $_POST['ship_to_billing'] ) && $_POST['ship_to_billing'] != '' ) {
143
+ wcal_common::wcal_set_cart_session( 'ship_to_billing', sanitize_text_field( wp_unslash( $_POST['ship_to_billing'] ) ) );
144
  }
145
  if ( isset( $_POST['shipping_first_name'] ) && $_POST['shipping_first_name'] != '' ) {
146
+ wcal_common::wcal_set_cart_session( 'shipping_first_name', sanitize_text_field( wp_unslash( $_POST['shipping_first_name'] ) ) );
147
  }
148
  if ( isset( $_POST['shipping_last_name'] ) && $_POST['shipping_last_name'] != '' ) {
149
+ wcal_common::wcal_set_cart_session( 'shipping_last_name', sanitize_text_field( wp_unslash( $_POST['shipping_last_name'] ) ) );
150
  }
151
  if ( isset( $_POST['shipping_company'] ) && $_POST['shipping_company'] != '' ) {
152
+ wcal_common::wcal_set_cart_session( 'shipping_company', sanitize_text_field( wp_unslash( $_POST['shipping_company'] ) ) );
153
  }
154
  if ( isset( $_POST['shipping_address_1'] ) && $_POST['shipping_address_1'] != '' ) {
155
+ wcal_common::wcal_set_cart_session( 'shipping_address_1', sanitize_text_field( wp_unslash( $_POST['shipping_address_1'] ) ) );
156
  }
157
  if ( isset( $_POST['shipping_address_2'] ) && $_POST['shipping_address_2'] != '' ) {
158
+ wcal_common::wcal_set_cart_session( 'shipping_address_2', sanitize_text_field( wp_unslash( $_POST['shipping_address_2'] ) ) );
159
  }
160
  if ( isset( $_POST['shipping_city'] ) && $_POST['shipping_city'] != '' ) {
161
+ wcal_common::wcal_set_cart_session( 'shipping_city', sanitize_text_field( wp_unslash( $_POST['shipping_city'] ) ) );
162
  }
163
  if ( isset( $_POST['shipping_state'] ) && $_POST['shipping_state'] != '' ) {
164
+ wcal_common::wcal_set_cart_session( 'shipping_state', sanitize_text_field( wp_unslash( $_POST['shipping_state'] ) ) );
165
  }
166
  if ( isset( $_POST['shipping_postcode'] ) && $_POST['shipping_postcode'] != '' ) {
167
+ wcal_common::wcal_set_cart_session( 'shipping_postcode', sanitize_text_field( wp_unslash( $_POST['shipping_postcode'] ) ) );
168
  }
169
  if ( isset( $_POST['shipping_country'] ) && $_POST['shipping_country'] != '' ) {
170
+ wcal_common::wcal_set_cart_session( 'shipping_country', sanitize_text_field( wp_unslash( $_POST['shipping_country'] ) ) );
171
  }
172
  // If a record is present in the guest cart history table for the same email id, then delete the previous records
173
+ $results_guest = $wpdb->get_results( // phpcs:ignore
174
+ $wpdb->prepare(
175
+ 'SELECT id FROM `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite` WHERE email_id = %s',
176
+ wcal_common::wcal_get_cart_session( 'billing_email' )
177
+ )
178
+ );
179
 
180
  if ( $results_guest ) {
181
  foreach ( $results_guest as $key => $value ) {
182
  $result = $wpdb->get_results(
183
  $wpdb->prepare(
184
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND recovered_cart = %s',
185
+ $value->id,
186
+ 0
187
  )
188
  );
189
  // update existing record and create new record if guest cart history table will have the same email id.
190
 
191
  if ( count( $result ) ) {
192
+ $wpdb->query( // phpcs:ignore
193
+ $wpdb->prepare(
194
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET cart_ignored = %s WHERE user_id = %s',
195
+ 1,
196
+ $value->id
197
+ )
198
+ );
199
  }
200
  }
201
  }
212
  $shipping_zipcode = $billing_zipcode = wcal_common::wcal_get_cart_session( 'billing_postcode' );
213
  }
214
  $shipping_charges = $woocommerce->cart->shipping_total;
215
+ $wpdb->query( // phpcs:ignore
216
+ $wpdb->prepare(
217
+ 'INSERT INTO `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite`( billing_first_name, billing_last_name, email_id, billing_zipcode, shipping_zipcode, shipping_charges ) VALUES ( %s, %s, %s, %s, %s, %s )',
218
+ $billing_first_name,
219
+ $billing_last_name,
220
+ wcal_common::wcal_get_cart_session( 'billing_email' ),
221
+ $billing_zipcode,
222
+ $shipping_zipcode,
223
+ $shipping_charges
224
+ )
225
+ );
226
 
227
  // Insert record in abandoned cart table for the guest user
228
  $user_id = $wpdb->insert_id;
232
  $cart_cut_off_time = $cut_off_time * 60;
233
  $compare_time = $current_time - $cart_cut_off_time;
234
 
235
+ $results = $wpdb->get_results( // phpcs:ignore
236
+ $wpdb->prepare(
237
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = %s AND recovered_cart = %s AND user_type = %s',
238
+ $user_id,
239
+ 0,
240
+ 0,
241
+ 'GUEST'
242
+ )
243
+ );
244
 
245
  $cart = array();
246
 
252
 
253
  if ( 0 == count( $results ) ) {
254
  $get_cookie = WC()->session->get_session_cookie();
255
+ //$cart_info = addslashes( json_encode( $cart ) );
256
+ $cart_info = json_encode( $cart );
257
+
258
+ $results = $wpdb->get_results(
259
+ $wpdb->prepare(
260
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE session_id LIKE %s AND cart_ignored = %s AND recovered_cart = %s',
261
+ $get_cookie[0],
262
+ 0,
263
+ 0
264
+ )
265
+ );
266
  if ( 0 == count( $results ) ) {
267
+ $wpdb->query( // phpcs:ignore
268
+ $wpdb->prepare(
269
+ 'INSERT INTO `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite`( user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, recovered_cart, user_type, session_id ) VALUES ( %s, %s, %s, %s, %s, %s, %s )',
270
+ $user_id,
271
+ $cart_info,
272
+ $current_time,
273
+ 0,
274
+ 0,
275
+ 'GUEST',
276
+ $get_cookie[0]
277
+ )
278
+ );
279
 
280
  $abandoned_cart_id = $wpdb->insert_id;
281
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
286
  if ( is_multisite() ) {
287
  // get main site's table prefix
288
  $main_prefix = $wpdb->get_blog_prefix( 1 );
289
+ $wpdb->query( // phpcS:ignore
290
+ $wpdb->prepare(
291
+ 'INSERT INTO `' . $main_prefix . 'usermeta`( user_id, meta_key, meta_value ) VALUES ( %s, %s, %s )',
292
+ $user_id,
293
+ '_woocommerce_persistent_cart',
294
+ $cart_info
295
+ )
296
+ );
297
 
298
  } else {
299
+ $wpdb->query( // phpcs:ignore
300
+ $wpdb->prepare(
301
+ 'INSERT INTO `' . $wpdb->prefix . 'usermeta`( user_id, meta_key, meta_value ) VALUES ( %s, %s, %s )',
302
+ $user_id,
303
+ '_woocommerce_persistent_cart',
304
+ $cart_info
305
+ )
306
+ );
307
  }
308
  } else {
309
+ $wpdb->query( // phpcS:ignore
310
+ $wpdb->prepare(
311
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET user_id = %s, abandoned_cart_info = %s, abandoned_cart_time = %s WHERE session_id = %s AND cart_ignored = %s',
312
+ $user_id,
313
+ $cart_info,
314
+ $current_time,
315
+ $get_cookie[0],
316
+ 0
317
+ )
318
+ );
319
+ $get_abandoned_record = $wpdb->get_results( // phpcS:ignore
320
+ $wpdb->prepare(
321
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = %s AND session_id = %s',
322
+ $user_id,
323
+ 0,
324
+ $get_cookie[0]
325
+ )
326
+ );
327
 
328
  if ( count( $get_abandoned_record ) > 0 ) {
329
  $abandoned_cart_id = $get_abandoned_record[0]->id;
330
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
331
  }
332
 
333
+ $wpdb->query( // phpcs:ignore
334
+ $wpdb->prepare(
335
+ 'INSERT INTO `' . $wpdb->prefix . 'usermeta`( user_id, meta_key, meta_value ) VALUES ( %s, %s, %s )',
336
+ $user_id,
337
+ '_woocommerce_persistent_cart',
338
+ $cart_info
339
+ )
340
+ );
341
  if ( is_multisite() ) {
342
  // get main site's table prefix
343
  $main_prefix = $wpdb->get_blog_prefix( 1 );
344
+ $wpdb->query( // phpcs:ignore
345
+ $wpdb->prepare(
346
+ 'INSERT INTO `' . $main_prefix . 'usermeta`( user_id, meta_key, meta_value ) VALUES ( %s, %s, %s )',
347
+ $user_id,
348
+ '_woocommerce_persistent_cart',
349
+ $cart_info
350
+ )
351
+ );
352
 
353
  } else {
354
+ $wpdb->query( // phpcs:ignore
355
+ $wpdb->prepare(
356
+ 'INSERT INTO `' . $wpdb->prefix . 'usermeta`( user_id, meta_key, meta_value ) VALUES ( %s, %s, %s )',
357
+ $user_id,
358
+ '_woocommerce_persistent_cart',
359
+ $cart_info
360
+ )
361
+ );
362
  }
363
  }
364
  }
includes/wcal_data_tracking_message.php CHANGED
@@ -1,71 +1,73 @@
1
  <?php
2
  /**
3
  * This class will add messages as needed informing users of data being tracked.
 
4
  * @author Tyche Softwares
5
  * @package Abandoned-Cart-Lite-for-WooCommerce/Tracking
6
  * @since 4.9
7
  */
8
  if ( ! defined( 'ABSPATH' ) ) {
9
- exit; // Exit if accessed directly.
10
  }
11
  if ( ! class_exists( 'Wcal_Tracking_msg' ) ) {
12
 
13
- /**
14
- * It will add messages as needed informing users of data being tracked.
15
- * @since 4.9
16
- */
17
- class Wcal_Tracking_msg {
 
18
 
19
- public function __construct() {
20
- // Product page notice for logged in users
21
- add_action( 'woocommerce_after_add_to_cart_button', array( &$this, 'wcal_add_logged_msg' ), 10 );
22
- add_action( 'wp_ajax_wcal_gdpr_refused', array( 'wcal_common', 'wcal_gdpr_refused' ) );
23
- }
24
 
25
- /**
26
- * Adds a message to be displayed for logged in users
27
- * Called on Shop & Product page
28
- *
29
- * @hook woocommerce_after_add_to_cart_button
30
- * woocommerce_before_shop_loop
31
- * @since 4.9
32
- */
33
- static function wcal_add_logged_msg() {
34
- if ( is_user_logged_in() ) {
35
 
36
- $registered_msg = get_option( 'wcal_logged_cart_capture_msg' );
37
- $gdpr_consent = get_user_meta( get_current_user_id(), 'wcal_gdpr_tracking_choice', true );
38
-
39
- if( $gdpr_consent === '' ) {
40
- $gdpr_consent = true;
41
- }
42
 
43
- if ( isset( $registered_msg ) && '' != $registered_msg && $gdpr_consent ) {
44
- wp_enqueue_script(
45
- 'wcal_registered_capture',
46
- plugins_url( '../assets/js/wcal_registered_user_capture.js', __FILE__ ),
47
- '',
48
- '',
49
- true
50
- );
51
 
52
- $vars = array(
53
- '_gdpr_after_no_thanks_msg' => htmlspecialchars( get_option( 'wcal_gdpr_opt_out_message' ), ENT_QUOTES ),
54
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
55
- );
 
 
 
 
56
 
57
- wp_localize_script(
58
- 'wcal_registered_capture',
59
- 'wcal_registered_capture_params',
60
- $vars
61
- );
62
-
63
- $registered_msg .= " <span id='wcal_gdpr_no_thanks'><a style='cursor: pointer' id='wcal_gdpr_no_thanks'>" . htmlspecialchars( get_option( 'wcal_gdpr_allow_opt_out' ), ENT_QUOTES ) . "</a></span>";
64
- echo "<span id='wcal_gdpr_message_block'><p><small>" . $registered_msg . "</small></p></span>";
65
- }
66
- }
67
- }
68
 
69
- } // end of class
70
- $Wcal_Tracking_msg = new Wcal_Tracking_msg();
 
 
 
 
 
 
 
 
 
 
 
 
71
  } // end IF
1
  <?php
2
  /**
3
  * This class will add messages as needed informing users of data being tracked.
4
+ *
5
  * @author Tyche Softwares
6
  * @package Abandoned-Cart-Lite-for-WooCommerce/Tracking
7
  * @since 4.9
8
  */
9
  if ( ! defined( 'ABSPATH' ) ) {
10
+ exit; // Exit if accessed directly.
11
  }
12
  if ( ! class_exists( 'Wcal_Tracking_msg' ) ) {
13
 
14
+ /**
15
+ * It will add messages as needed informing users of data being tracked.
16
+ *
17
+ * @since 4.9
18
+ */
19
+ class Wcal_Tracking_msg {
20
 
21
+ public function __construct() {
22
+ // Product page notice for logged in users
23
+ add_action( 'woocommerce_after_add_to_cart_button', array( &$this, 'wcal_add_logged_msg' ), 10 );
24
+ add_action( 'wp_ajax_wcal_gdpr_refused', array( 'wcal_common', 'wcal_gdpr_refused' ) );
25
+ }
26
 
27
+ /**
28
+ * Adds a message to be displayed for logged in users
29
+ * Called on Shop & Product page
30
+ *
31
+ * @hook woocommerce_after_add_to_cart_button
32
+ * woocommerce_before_shop_loop
33
+ * @since 4.9
34
+ */
35
+ static function wcal_add_logged_msg() {
36
+ if ( is_user_logged_in() ) {
37
 
38
+ $registered_msg = get_option( 'wcal_logged_cart_capture_msg' );
39
+ $gdpr_consent = get_user_meta( get_current_user_id(), 'wcal_gdpr_tracking_choice', true );
 
 
 
 
40
 
41
+ if ( $gdpr_consent === '' ) {
42
+ $gdpr_consent = true;
43
+ }
 
 
 
 
 
44
 
45
+ if ( isset( $registered_msg ) && '' != $registered_msg && $gdpr_consent ) {
46
+ wp_enqueue_script(
47
+ 'wcal_registered_capture',
48
+ plugins_url( '../assets/js/wcal_registered_user_capture.js', __FILE__ ),
49
+ '',
50
+ '',
51
+ true
52
+ );
53
 
54
+ $vars = array(
55
+ '_gdpr_after_no_thanks_msg' => htmlspecialchars( get_option( 'wcal_gdpr_opt_out_message' ), ENT_QUOTES ),
56
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
57
+ );
 
 
 
 
 
 
 
58
 
59
+ wp_localize_script(
60
+ 'wcal_registered_capture',
61
+ 'wcal_registered_capture_params',
62
+ $vars
63
+ );
64
+
65
+ $registered_msg .= " <span id='wcal_gdpr_no_thanks'><a style='cursor: pointer' id='wcal_gdpr_no_thanks'>" . htmlspecialchars( get_option( 'wcal_gdpr_allow_opt_out' ), ENT_QUOTES ) . '</a></span>';
66
+ echo "<span id='wcal_gdpr_message_block'><p><small>" . $registered_msg . '</small></p></span>';
67
+ }
68
+ }
69
+ }
70
+
71
+ } // end of class
72
+ $Wcal_Tracking_msg = new Wcal_Tracking_msg();
73
  } // end IF
includes/wcal_process_base.php CHANGED
@@ -1,31 +1,30 @@
1
- <?php
2
 
3
  class Wcal_Process_Base {
4
-
5
- public function __construct() {
6
- // Hook into that action that'll fire every 15 minutes
7
- add_action( 'woocommerce_ac_send_email_action', array( &$this, 'wcal_process_handler' ), 11 );
8
-
9
- }
10
-
11
- public function wcal_process_handler() {
12
- // add any new reminder methods added in the future for cron here
13
- $reminders_list = array( 'emails' );
14
-
15
- if( is_array( $reminders_list ) && count( $reminders_list ) > 0 ) {
16
- foreach( $reminders_list as $reminder_type ) {
17
- switch( $reminder_type ) {
18
- case 'emails':
19
- $wcal_cron = new woocommerce_abandon_cart_cron();
20
- $wcal_cron->wcal_send_email_notification();
21
- break;
22
- }
23
-
24
- }
25
- }
26
-
27
- }
28
-
29
  }
30
  new Wcal_Process_Base();
31
- ?>
1
+ <?php
2
 
3
  class Wcal_Process_Base {
4
+
5
+ public function __construct() {
6
+ // Hook into that action that'll fire every 15 minutes
7
+ add_action( 'woocommerce_ac_send_email_action', array( &$this, 'wcal_process_handler' ), 11 );
8
+
9
+ }
10
+
11
+ public function wcal_process_handler() {
12
+ // add any new reminder methods added in the future for cron here
13
+ $reminders_list = array( 'emails' );
14
+
15
+ if ( is_array( $reminders_list ) && count( $reminders_list ) > 0 ) {
16
+ foreach ( $reminders_list as $reminder_type ) {
17
+ switch ( $reminder_type ) {
18
+ case 'emails':
19
+ $wcal_cron = new woocommerce_abandon_cart_cron();
20
+ $wcal_cron->wcal_send_email_notification();
21
+ break;
22
+ }
23
+ }
24
+ }
25
+
26
+ }
27
+
 
28
  }
29
  new Wcal_Process_Base();
30
+
readme.txt CHANGED
@@ -4,7 +4,7 @@ Contributors: ashokrane, pinal.shah, bhavik.kiri, chetnapatel, tychesoftwares, d
4
  Tags: cart abandonment, abandon cart, cart recovery, recover woocommerce cart, increase woocommerce conversion rate, increase sales with woocommerce
5
  Author URI: https://www.tychesoftwares.com/
6
  Requires at least: 1.3
7
- Tested up to: 5.5
8
  Stable tag: trunk
9
  Requires PHP: 5.6
10
  License: GPLv2 or late
@@ -223,6 +223,12 @@ The admin can use the merge code `{{cart.unsubscribe}}' in the email templates.
223
 
224
  == Changelog ==
225
 
 
 
 
 
 
 
226
  = 5.8.1 (26.08.2020) =
227
  * Fix - When the plugin contained thousands of records, the Abandoned Orders page failed to load.
228
  * Fix - The send email action schedule raised some warnings.
4
  Tags: cart abandonment, abandon cart, cart recovery, recover woocommerce cart, increase woocommerce conversion rate, increase sales with woocommerce
5
  Author URI: https://www.tychesoftwares.com/
6
  Requires at least: 1.3
7
+ Tested up to: 5.5.1
8
  Stable tag: trunk
9
  Requires PHP: 5.6
10
  License: GPLv2 or late
223
 
224
  == Changelog ==
225
 
226
+ = 5.8.2 (30.10.2020) =
227
+ * Fix - Improved the code run in the action scheduler to include performance fixes.
228
+ * Fix - Multiple instances of the woocommerce_ac_send_email action were observed in the Tools->Pending Actions.
229
+ * Fix - Included sanitization of data & SQL queries for security purposes.
230
+ * Fix - Optimized the plugin to use latest versions of JS and other libraries already present in WordPress.
231
+
232
  = 5.8.1 (26.08.2020) =
233
  * Fix - When the plugin contained thousands of records, the Abandoned Orders page failed to load.
234
  * Fix - The send email action schedule raised some warnings.
uninstall.php CHANGED
@@ -67,6 +67,8 @@ if ( is_multisite() ) { // Multisite.
67
 
68
  delete_blog_option( $blog_id_number, 'ac_lite_delete_redundant_queries' );
69
  delete_blog_option( $blog_id_number, 'wcal_enable_cart_emails' );
 
 
70
  } else {
71
 
72
  require_once ABSPATH . 'wp-admin/includes/upgrade.php';
@@ -138,4 +140,5 @@ delete_option( 'wcal_new_default_templates' );
138
 
139
  delete_option( 'ac_lite_delete_redundant_queries' );
140
  delete_option( 'wcal_enable_cart_emails' );
141
- delete_option( 'wcal_scheduler_update_dismiss' );
 
67
 
68
  delete_blog_option( $blog_id_number, 'ac_lite_delete_redundant_queries' );
69
  delete_blog_option( $blog_id_number, 'wcal_enable_cart_emails' );
70
+ delete_blog_option( $blog_id_number, 'wcal_scheduler_update_dismiss' );
71
+ delete_blog_option( $blog_id_number, 'wcal_add_email_status_col' );
72
  } else {
73
 
74
  require_once ABSPATH . 'wp-admin/includes/upgrade.php';
140
 
141
  delete_option( 'ac_lite_delete_redundant_queries' );
142
  delete_option( 'wcal_enable_cart_emails' );
143
+ delete_option( 'wcal_scheduler_update_dismiss' );
144
+ delete_option( 'wcal_add_email_status_col' );
woocommerce-ac.php CHANGED
@@ -1,39 +1,37 @@
1
  <?php
2
- /*
3
- * Plugin Name: Abandoned Cart Lite for WooCommerce
4
- * Plugin URI: http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro
5
- * Description: This plugin captures abandoned carts by logged-in users & emails them about it.
6
- * <strong><a href="http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro">Click here to get the
7
- * PRO Version.</a></strong>
8
- * Version: 5.8.1
9
- * Author: Tyche Softwares
10
- * Author URI: http://www.tychesoftwares.com/
11
- * Text Domain: woocommerce-abandoned-cart
12
- * Domain Path: /i18n/languages/
13
- * Requires PHP: 5.6
14
- * WC requires at least: 3.0.0
15
- * WC tested up to: 4.4.1
16
- *
17
- * @package Abandoned-Cart-Lite-for-WooCommerce
18
- */
19
-
20
- require_once( 'class-wcal-update.php' );
21
- require_once( 'includes/wcal_class-guest.php' );
22
- require_once( 'includes/class-wcal-default-template-settings.php' );
23
- require_once( 'includes/class-wcal-delete-handler.php' );
24
- require_once( 'includes/classes/class-wcal-aes.php' );
25
- require_once( 'includes/classes/class-wcal-aes-counter.php' );
26
- require_once( 'includes/wcal-common.php' );
27
-
28
- require_once( 'includes/class-wcal-admin-notice.php' );
29
- require_once( 'includes/wcal_data_tracking_message.php' );
30
- require_once( 'includes/admin/wcal_privacy_erase.php' );
31
- require_once( 'includes/admin/wcal_privacy_export.php' );
32
- require_once( 'includes/admin/class-wcal-abandoned-cart-details.php' );
33
-
34
- require_once( 'includes/admin/wcap_pro_settings.php' );
35
- require_once( 'includes/admin/wcap_pro_settings_callbacks.php' );
36
- require_once( 'includes/admin/wcap_add_cart_popup_modal.php' );
37
 
38
  load_plugin_textdomain( 'woocommerce-abandoned-cart', false, basename( dirname( __FILE__ ) ) . '/i18n/languages' );
39
 
@@ -61,33 +59,73 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
61
  * @package Abandoned-Cart-Lite-for-WooCommerce/Core
62
  */
63
  class woocommerce_abandon_cart_lite {
64
- var $one_hour;
65
- var $three_hours;
66
- var $six_hours;
67
- var $twelve_hours;
68
- var $one_day;
69
- var $one_week;
70
- var $duration_range_select = array();
71
- var $start_end_dates = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  /**
73
  * The constructor will add the hooks, filters and the variable which will be used all over the plugin.
74
  *
75
  * @since 1.0
76
  */
77
  public function __construct() {
78
- if ( !defined( 'WCAL_PLUGIN_URL' ) ) {
79
  define( 'WCAL_PLUGIN_URL', untrailingslashit( plugins_url( '/', __FILE__ ) ) );
80
  }
81
 
82
  if ( ! defined( 'WCAL_PLUGIN_VERSION' ) ) {
83
- define( 'WCAL_PLUGIN_VERSION', '5.8.1' );
84
  }
85
- $this->one_hour = 60 * 60;
86
- $this->three_hours = 3 * $this->one_hour;
87
- $this->six_hours = 6 * $this->one_hour;
88
- $this->twelve_hours = 12 * $this->one_hour;
89
- $this->one_day = 24 * $this->one_hour;
90
- $this->one_week = 7 * $this->one_day;
91
  $this->duration_range_select = array(
92
  'yesterday' => 'Yesterday',
93
  'today' => 'Today',
@@ -95,37 +133,37 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
95
  'last_fifteen' => 'Last 15 days',
96
  'last_thirty' => 'Last 30 days',
97
  'last_ninety' => 'Last 90 days',
98
- 'last_year_days' => 'Last 365'
99
  );
100
 
101
  $this->start_end_dates = array(
102
  'yesterday' => array(
103
- 'start_date' => date( "d M Y", ( current_time( 'timestamp' ) - 24 * 60 * 60 ) ),
104
- 'end_date' => date( "d M Y", ( current_time( 'timestamp' ) - 7 * 24 * 60 * 60 ) ),
105
  ),
106
  'today' => array(
107
- 'start_date' => date( "d M Y", ( current_time( 'timestamp' ) ) ),
108
- 'end_date' => date( "d M Y", ( current_time( 'timestamp' ) ) )
109
  ),
110
  'last_seven' => array(
111
- 'start_date' => date( "d M Y", ( current_time( 'timestamp' ) - 7*24*60*60 ) ),
112
- 'end_date' => date( "d M Y", ( current_time( 'timestamp' ) ) )
113
  ),
114
  'last_fifteen' => array(
115
- 'start_date' => date( "d M Y", ( current_time( 'timestamp' ) - 15*24*60*60 ) ),
116
- 'end_date' => date( "d M Y", ( current_time( 'timestamp' ) ) )
117
  ),
118
  'last_thirty' => array(
119
- 'start_date' => date( "d M Y", ( current_time( 'timestamp' ) - 30*24*60*60 ) ),
120
- 'end_date' => date( "d M Y", ( current_time( 'timestamp' ) ) )
121
  ),
122
  'last_ninety' => array(
123
- 'start_date' => date( "d M Y", ( current_time( 'timestamp' ) - 90*24*60*60 ) ),
124
- 'end_date' => date( "d M Y", ( current_time( 'timestamp' ) ) )
125
  ),
126
  'last_year_days' => array(
127
- 'start_date' => date( "d M Y", ( current_time( 'timestamp' ) - 365*24*60*60 ) ),
128
- 'end_date' => date( "d M Y", ( current_time( 'timestamp' ) ) )
129
  ),
130
  );
131
 
@@ -134,10 +172,10 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
134
  register_deactivation_hook( __FILE__, array( &$this, 'wcal_deactivate' ) );
135
 
136
  // Action Scheduler for Cron.
137
- require_once( 'includes/libraries/action-scheduler/action-scheduler.php' );
138
  add_action( 'init', array( &$this, 'wcal_add_scheduled_action' ) );
139
- require_once( 'cron/wcal_send_email.php' );
140
- require_once( 'includes/wcal_process_base.php' );
141
 
142
  // WordPress Administration Menu.
143
  add_action( 'admin_menu', array( &$this, 'wcal_admin_menu' ) );
@@ -154,25 +192,26 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
154
  add_action( 'admin_init', array( &$this, 'wcal_action_admin_init' ) );
155
 
156
  // Update the options as per settings API.
157
- add_action( 'admin_init', array( 'Wcal_Update', 'wcal_update_db_check' ) );
 
158
 
159
- // Wordpress settings API
160
- add_action( 'admin_init', array( &$this, 'wcal_initialize_plugin_options' ) );
161
 
162
- // Language Translation
163
- add_action ( 'init', array( &$this, 'wcal_update_po_file' ) );
164
 
165
- add_action ( 'init', array ( &$this, 'wcal_add_component_file') );
166
 
167
- // track links
168
- add_filter( 'template_include', array( &$this, 'wcal_email_track_links' ), 99, 1 );
169
 
170
- //It will used to unsubcribe the emails.
171
- add_action( 'template_include', array( &$this, 'wcal_email_unsubscribe'),99, 1 );
172
 
173
- add_action ( 'admin_enqueue_scripts', array( &$this, 'wcal_enqueue_scripts_js' ) );
174
- add_action ( 'admin_enqueue_scripts', array( &$this, 'wcal_enqueue_scripts_css' ) );
175
- //delete abandoned order after X number of days
176
  if ( class_exists( 'Wcal_Delete_Handler' ) ) {
177
  add_action( 'wcal_clear_carts', array( 'Wcal_Delete_Handler', 'wcal_delete_abandoned_carts_after_x_days' ) );
178
  }
@@ -185,21 +224,21 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
185
  add_action( 'wp_ajax_wcal_abandoned_cart_info', array( &$this, 'wcal_abandoned_cart_info' ) );
186
  add_action( 'wp_ajax_wcal_dismiss_admin_notice', array( &$this, 'wcal_dismiss_admin_notice' ) );
187
 
188
- add_filter( 'ts_tracker_data', array( 'wcal_common', 'ts_add_plugin_tracking_data' ), 10, 1 );
189
- add_filter( 'ts_tracker_opt_out_data', array( 'wcal_common', 'ts_get_data_for_opt_out' ), 10, 1 );
190
- add_filter( 'ts_deativate_plugin_questions', array( &$this, 'wcal_deactivate_add_questions' ), 10, 1 );
191
  }
192
 
193
- // Plugin Settings link in WP->Plugins page
194
  $plugin = plugin_basename( __FILE__ );
195
- add_action( "plugin_action_links_$plugin", array( &$this, 'wcal_settings_link' ) );
196
 
197
- add_action( 'admin_init', array( $this, 'wcal_preview_emails' ) );
198
- add_action( 'init', array( $this, 'wcal_app_output_buffer') );
199
 
200
- add_filter( 'admin_footer_text', array( $this, 'wcal_admin_footer_text' ), 1 );
201
 
202
- add_action( 'admin_notices', array( 'Wcal_Admin_Notice', 'wcal_show_db_update_notice' ) );
203
 
204
  include_once 'includes/frontend/wcal_frontend.php';
205
  }
@@ -210,12 +249,15 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
210
  public static function wcal_add_scheduled_action() {
211
  if ( false === as_next_scheduled_action( 'woocommerce_ac_send_email_action' ) ) {
212
  wp_clear_scheduled_hook( 'woocommerce_ac_send_email_action' ); // Remove the cron job is present.
213
- as_schedule_recurring_action( time(), 900, 'woocommerce_ac_send_email_action' ); // Schedule recurring action.
214
  }
215
  }
216
-
217
  /**
218
- * Add Settings link to WP->Plugins page
 
 
 
219
  * @since 5.3.0
220
  */
221
  public static function wcal_settings_link( $links ) {
@@ -227,47 +269,49 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
227
  /**
228
  * It will load the boilerplate components file. In this file we have included all boilerplate files.
229
  * We need to inlcude this file after the init hook.
 
230
  * @hook init
231
  */
232
- public static function wcal_add_component_file () {
233
  if ( is_admin() ) {
234
- require_once( 'includes/wcal_all_component.php' );
235
 
236
  }
237
  }
238
  /**
239
  * It will add the Questions while admin deactivate the plugin.
240
- * @hook ts_deativate_plugin_questions
241
- * @param array $wcal_add_questions Blank array
 
242
  * @return array $wcal_add_questions List of all questions.
243
  */
244
- public static function wcal_deactivate_add_questions ( $wcal_add_questions ) {
245
 
246
  $wcal_add_questions = array(
247
  0 => array(
248
  'id' => 4,
249
- 'text' => __( "Emails are not being sent to customers.", "woocommerce-abandoned-cart" ),
250
  'input_type' => '',
251
- 'input_placeholder' => ''
252
- ),
253
- 1 => array(
254
  'id' => 5,
255
- 'text' => __( "Capturing of cart and other information was not satisfactory.", "woocommerce-abandoned-cart" ),
256
  'input_type' => '',
257
- 'input_placeholder' => ''
258
  ),
259
  2 => array(
260
  'id' => 6,
261
- 'text' => __( "I cannot see abandoned cart reminder emails records.", "woocommerce-abandoned-cart" ),
262
  'input_type' => '',
263
- 'input_placeholder' => ''
264
  ),
265
  3 => array(
266
  'id' => 7,
267
- 'text' => __( "I want to upgrade the plugin to the PRO version.", "woocommerce-abandoned-cart" ),
268
  'input_type' => '',
269
- 'input_placeholder' => ''
270
- )
271
 
272
  );
273
  return $wcal_add_questions;
@@ -275,28 +319,31 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
275
 
276
  /**
277
  * Replace Merge tags in email previews.
 
 
 
278
  * @since 5.8
279
  */
280
- function replace_mergetags( $content ) {
281
-
282
  $admin_args = array(
283
  'role' => 'administrator',
284
  'fields' => array( 'id' ),
285
  );
286
 
287
- $admin_usr = get_users( $admin_args );
288
- $uid = $admin_usr[0]->id;
289
- $admin_phone = get_user_meta( $uid, 'billing_phone', true );
290
 
291
  $wcal_price = wc_price( '150' );
292
  $wcal_total_price = wc_price( '300' );
293
 
294
- $allowed_html = [
295
- 'span' => [
296
- 'class' => [],
297
- ],
298
- ];
299
- $plugins_url = esc_url( plugins_url() );
300
  $replace_data['products_cart'] = "<table border='0' width='100%' cellspacing='0' cellpadding='0'><b>Your Shopping Cart</b>
301
  <tbody>
302
  <tr>
@@ -312,111 +359,118 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
312
 
313
  </tr>
314
  <tr style='background-color:#f4f5f4;'>
315
- <td><img src = '$plugins_url/woocommerce-abandoned-cart/assets/images/spectre.jpg' height='40px' width='40px'></td><td>Spectre</td><td>" . wp_kses( $wcal_price, $allowed_html ) . "</td><td>2</td><td>" . wp_kses( $wcal_total_price, $allowed_html ) . "</td>
316
  </tr>
317
  <tr>
318
  <td>&nbsp;</td>
319
  <td>&nbsp;</td>
320
  <td>&nbsp;</td>
321
  <th>Cart Total:</th>
322
- <td>" . wp_kses( $wcal_total_price, $allowed_html ) . "</td>
323
  </tr>
324
 
325
  </tbody>
326
- </table>";
327
- $replace_data['admin_phone'] = $admin_phone;
328
- $replace_data['site_title'] = get_bloginfo( 'name' );
329
- $replace_data['site_url'] = get_option( 'siteurl' );
330
 
331
-
332
  $content = str_ireplace( '{{products.cart}}', $replace_data['products_cart'], $content );
333
- $content = str_ireplace( '{{admin.phone}}', $replace_data['admin_phone'], $content );
334
- $content = str_ireplace( '{{customer.firstname}}', "John", $content );
335
- $content = str_ireplace( '{{customer.lastname}}', "Doe", $content );
336
- $content = str_ireplace( '{{customer.fullname}}', "John Doe", $content );
337
  $content = str_ireplace( 'site_title', $replace_data['site_title'], $content );
338
  $content = str_ireplace( 'site_url', $replace_data['site_url'], $content );
339
-
340
  return $content;
341
  }
342
-
343
  /**
344
  * It will ganerate the preview email template.
 
345
  * @hook admin_init
346
  * @globals mixed $woocommerce
347
  * @since 2.5
348
  */
349
  public function wcal_preview_emails() {
350
  global $woocommerce;
351
-
352
- if ( isset( $_GET[ 'id' ] ) && 0 < $_GET['id'] ) {
353
  global $wpdb;
354
- $content = $wpdb->get_var( $wpdb->prepare( "SELECT body FROM `" . $wpdb->prefix . "ac_email_templates_lite` WHERE id = %d", absint( $_GET['id'] ) ) );
 
 
 
 
 
 
355
  $content = $this->replace_mergetags( $content );
356
  }
357
 
358
- if ( isset( $_GET['wcal_preview_woocommerce_mail'] ) ) {
359
- if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-abandoned-cart' ) ) {
360
  die( 'Security check' );
361
  }
362
  $message = '';
363
- // create a new email
364
  if ( $woocommerce->version < '2.3' ) {
365
  global $email_heading;
366
  ob_start();
367
 
368
- include( 'views/wcal-wc-email-template-preview.php' );
369
  $mailer = WC()->mailer();
370
  $message = ob_get_clean();
371
  $email_heading = __( 'HTML Email Template', 'woocommerce-abandoned-cart' );
372
- $message = $mailer->wrap_message( $email_heading, $message );
373
  } else {
374
- // load the mailer class
375
- $mailer = WC()->mailer();
376
- // get the preview email subject
377
  $email_heading = __( 'Abandoned cart Email Template', 'woocommerce-abandoned-cart' );
378
- // get the preview email content
379
  ob_start();
380
- if ( isset( $_GET[ 'id' ] ) && 0 < $_GET['id'] ) {
381
  $message = stripslashes( $content );
382
  } else {
383
- include( 'views/wcal-wc-email-template-preview.php' );
384
  $message = ob_get_clean();
385
  }
386
- // create a new email
387
- $email = new WC_Email();
388
- // wrap the content with the email template and then add styles
389
- $message = $email->style_inline( $mailer->wrap_message( $email_heading, $message ) );
390
  }
391
- echo $message;
392
  exit;
393
  }
394
 
395
- if ( isset( $_GET['wcal_preview_mail'] ) ) {
396
- if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-abandoned-cart' ) ) {
397
  die( 'Security check' );
398
  }
399
- // get the preview email content
400
  ob_start();
401
- if ( isset( $_GET[ 'id' ] ) && 0 < $_GET['id'] ) {
402
  $message = stripslashes( $content );
403
  } else {
404
- include_once( 'views/wcal-email-template-preview.php' );
405
  $message = ob_get_clean();
406
  }
407
- // print the preview email
408
- echo $message;
409
  exit;
410
  }
411
  }
412
 
413
  /**
414
  * In this version we have allowed customer to transalte the plugin string using .po and .pot file.
 
415
  * @hook init
416
  * @return $loaded
417
  * @since 1.6
418
  */
419
- function wcal_update_po_file() {
420
  /*
421
  * Due to the introduction of language packs through translate.wordpress.org, loading our textdomain is complex.
422
  *
@@ -424,34 +478,36 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
424
  */
425
  $domain = 'woocommerce-abandoned-cart';
426
  $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
427
- if ( $loaded = load_textdomain( $domain, trailingslashit( WP_LANG_DIR ) . $domain . '-' . $locale . '.mo' ) ) {
 
428
  return $loaded;
429
  } else {
430
- load_plugin_textdomain( $domain, FALSE, basename( dirname( __FILE__ ) ) . '/i18n/languages/' );
431
  }
432
  }
433
 
434
  /**
435
  * It will create the plugin tables & the options reqired for plugin.
 
436
  * @hook register_activation_hook
437
  * @globals mixed $wpdb
438
  * @since 1.0
439
  */
440
  public static function wcal_activate() {
441
 
442
- // check whether its a multi site install or a single site install
443
  if ( is_multisite() ) {
444
-
445
  $blog_list = get_sites();
446
  foreach ( $blog_list as $blog_list_key => $blog_list_value ) {
447
- if ( $blog_list_value->blog_id > 1 ) { // child sites
448
  $blog_id = $blog_list_value->blog_id;
449
  self::wcal_process_activate( $blog_id );
450
- } else { // parent site
451
  self::wcal_process_activate();
452
  }
453
  }
454
- } else { // single site
455
  self::wcal_process_activate();
456
  }
457
  }
@@ -476,112 +532,111 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
476
  public static function wcal_process_activate( $blog_id = 0 ) {
477
  global $wpdb;
478
 
479
- $db_prefix = ( $blog_id === 0 ) ? $wpdb->prefix : $wpdb->prefix . $blog_id . "_";
480
 
481
  $wcap_collate = '';
482
  if ( $wpdb->has_cap( 'collation' ) ) {
483
  $wcap_collate = $wpdb->get_charset_collate();
484
  }
485
- $table_name = $db_prefix . "ac_email_templates_lite";
486
- $sql = "CREATE TABLE IF NOT EXISTS $table_name (
487
- `id` int(11) NOT NULL AUTO_INCREMENT,
488
- `subject` text NOT NULL,
489
- `body` mediumtext NOT NULL,
490
- `is_active` enum('0','1') NOT NULL,
491
- `frequency` int(11) NOT NULL,
492
- `day_or_hour` enum('Days','Hours') NOT NULL,
493
- `template_name` text NOT NULL,
494
- `is_wc_template` enum('0','1') NOT NULL,
495
- `default_template` int(11) NOT NULL,
496
- `wc_email_header` varchar(50) NOT NULL,
497
- PRIMARY KEY (`id`)
498
- ) $wcap_collate AUTO_INCREMENT=1 ";
499
-
500
- require_once ( ABSPATH . 'wp-admin/includes/upgrade.php' );
501
- dbDelta( $sql );
502
-
503
- $sent_table_name = $db_prefix . "ac_sent_history_lite";
504
-
505
- $sql_query = "CREATE TABLE IF NOT EXISTS $sent_table_name (
506
- `id` int(11) NOT NULL auto_increment,
507
- `template_id` varchar(40) collate utf8_unicode_ci NOT NULL,
508
- `abandoned_order_id` int(11) NOT NULL,
509
- `sent_time` datetime NOT NULL,
510
- `sent_email_id` text COLLATE utf8_unicode_ci NOT NULL,
511
- PRIMARY KEY (`id`)
512
- ) $wcap_collate AUTO_INCREMENT=1 ";
513
-
514
- require_once ( ABSPATH . 'wp-admin/includes/upgrade.php' );
515
- dbDelta ( $sql_query );
516
-
517
- $ac_history_table_name = $db_prefix . "ac_abandoned_cart_history_lite";
518
-
519
- $history_query = "CREATE TABLE IF NOT EXISTS $ac_history_table_name (
520
- `id` int(11) NOT NULL AUTO_INCREMENT,
521
- `user_id` int(11) NOT NULL,
522
- `abandoned_cart_info` text COLLATE utf8_unicode_ci NOT NULL,
523
- `abandoned_cart_time` int(11) NOT NULL,
524
- `cart_ignored` enum('0','1') COLLATE utf8_unicode_ci NOT NULL,
525
- `recovered_cart` int(11) NOT NULL,
526
- `user_type` text,
527
- `unsubscribe_link` enum('0','1') COLLATE utf8_unicode_ci NOT NULL,
528
- `session_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
529
- PRIMARY KEY (`id`)
530
- ) $wcap_collate";
531
-
532
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
533
- dbDelta( $history_query );
534
-
535
- $guest_table = $db_prefix."ac_guest_abandoned_cart_history_lite" ;
536
- $query_guest_table = "SHOW TABLES LIKE '$guest_table' ";
537
- $result_guest_table = $wpdb->get_results( $query_guest_table );
538
-
539
- if ( 0 == count( $result_guest_table ) ) {
540
- $ac_guest_history_table_name = $db_prefix . "ac_guest_abandoned_cart_history_lite";
541
- $ac_guest_history_query = "CREATE TABLE IF NOT EXISTS $ac_guest_history_table_name (
542
- `id` int(15) NOT NULL AUTO_INCREMENT,
543
- `billing_first_name` text,
544
- `billing_last_name` text,
545
- `billing_company_name` text,
546
- `billing_address_1` text,
547
- `billing_address_2` text,
548
- `billing_city` text,
549
- `billing_county` text,
550
- `billing_zipcode` text,
551
- `email_id` text,
552
- `phone` text,
553
- `ship_to_billing` text,
554
- `order_notes` text,
555
- `shipping_first_name` text,
556
- `shipping_last_name` text,
557
- `shipping_company_name` text,
558
- `shipping_address_1` text,
559
- `shipping_address_2` text,
560
- `shipping_city` text,
561
- `shipping_county` text,
562
- `shipping_zipcode` double,
563
- `shipping_charges` double,
564
  PRIMARY KEY (`id`)
565
- ) $wcap_collate AUTO_INCREMENT=63000000";
566
- require_once( ABSPATH . 'wp-admin/includes/upgrade.php');
567
- $wpdb->query( $ac_guest_history_query );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  }
569
 
570
- // Default templates: function call to create default templates.
571
- $check_table_empty = $wpdb->get_var( "SELECT COUNT(*) FROM `" . $db_prefix . "ac_email_templates_lite`" );
572
 
573
  /**
574
  * This is add for thos user who Install the plguin first time.
575
  * So for them this option will be cheked.
576
  */
577
- if( 0 === $blog_id ) {
578
  if ( ! get_option( 'wcal_new_default_templates' ) ) {
579
- if ( 0 == $check_table_empty ) {
580
- $default_template = new Wcal_Default_Template_Settings;
581
  $default_template->wcal_create_default_templates( $db_prefix, $blog_id );
582
  }
583
  }
584
-
 
 
585
  if ( ! get_option( 'ac_lite_track_guest_cart_from_cart_page' ) ) {
586
  add_option( 'ac_lite_track_guest_cart_from_cart_page', 'on' );
587
  }
@@ -603,7 +658,9 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
603
  $default_template->wcal_create_default_templates( $db_prefix, $blog_id );
604
  }
605
  }
606
-
 
 
607
  if ( ! get_blog_option( $blog_id, 'ac_lite_track_guest_cart_from_cart_page' ) ) {
608
  add_blog_option( $blog_id, 'ac_lite_track_guest_cart_from_cart_page', 'on' );
609
  }
@@ -614,7 +671,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
614
  if ( ! get_blog_option( $blog_id, 'wcal_from_email' ) ) {
615
  add_blog_option( $blog_id, 'wcal_from_email', $wcal_get_admin_email );
616
  }
617
-
618
  if ( ! get_blog_option( $blog_id, 'wcal_reply_email' ) ) {
619
  add_blog_option( $blog_id, 'wcal_reply_email', $wcal_get_admin_email );
620
  }
@@ -624,17 +681,18 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
624
 
625
  /**
626
  * It will add the section, field, & registres the plugin fields using Settings API.
 
627
  * @hook admin_init
628
  * @since 2.5
629
  */
630
- function wcal_initialize_plugin_options() {
631
 
632
- // First, we register a section. This is necessary since all future options must belong to a
633
  add_settings_section(
634
- 'ac_lite_general_settings_section', // ID used to identify this section and with which to register options
635
- __( 'Settings', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page
636
- array( $this, 'ac_lite_general_options_callback' ), // Callback used to render the description of the section
637
- 'woocommerce_ac_page' // Page on which to add this section of options
638
  );
639
 
640
  add_settings_field(
@@ -643,7 +701,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
643
  array( $this, 'wcal_enable_cart_emails_callback' ),
644
  'woocommerce_ac_page',
645
  'ac_lite_general_settings_section',
646
- array( __( "Yes, enable the abandoned cart emails.", 'woocommerce-abandoned-cart' ) )
647
  );
648
 
649
  add_settings_field(
@@ -664,7 +722,6 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
664
  array( __( 'Automatically delete abandoned cart orders after X days.', 'woocommerce-abandoned-cart' ) )
665
  );
666
 
667
-
668
  add_settings_field(
669
  'ac_lite_email_admin_on_recovery',
670
  __( 'Email admin On Order Recovery', 'woocommerce-abandoned-cart' ),
@@ -674,14 +731,13 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
674
  array( __( 'Sends email to Admin if an Abandoned Cart Order is recovered.', 'woocommerce-abandoned-cart' ) )
675
  );
676
 
677
-
678
  add_settings_field(
679
- 'ac_lite_track_guest_cart_from_cart_page',
680
- __( 'Start tracking from Cart Page', 'woocommerce-abandoned-cart' ),
681
- array( $this, 'wcal_track_guest_cart_from_cart_page_callback' ),
682
- 'woocommerce_ac_page',
683
- 'ac_lite_general_settings_section',
684
- array( __( 'Enable tracking of abandoned products & carts even if customer does not visit the checkout page or does not enter any details on the checkout page like Name or Email. Tracking will begin as soon as a visitor adds a product to their cart and visits the cart page.', 'woocommerce-abandoned-cart' ) )
685
  );
686
 
687
  add_settings_field(
@@ -710,7 +766,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
710
  'ac_lite_general_settings_section',
711
  array( __( '<br>In compliance with GDPR, allow the site visitor (guests & registered users) to opt out from cart tracking. This message will be displayed in conjunction with the GDPR message above.</i>', 'woocommerce-abandoned-cart' ) )
712
  );
713
-
714
  add_settings_field(
715
  'wcal_gdpr_opt_out_message',
716
  __( 'Message to be displayed when the user chooses to opt out of cart tracking.', 'woocommerce-abandoned-cart' ),
@@ -722,44 +778,44 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
722
 
723
  /**
724
  * New section for the Adding the abandoned cart setting.
 
725
  * @since 4.7
726
  */
727
-
728
  add_settings_section(
729
- 'ac_email_settings_section', // ID used to identify this section and with which to register options
730
- __( 'Settings for abandoned cart recovery emails', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page
731
- array( $this, 'wcal_email_callback' ), // Callback used to render the description of the section
732
- 'woocommerce_ac_email_page' // Page on which to add this section of options
733
  );
734
 
735
  add_settings_field(
736
- 'wcal_from_name',
737
- __( '"From" Name', 'woocommerce-abandoned-cart' ),
738
- array( $this, 'wcal_from_name_callback' ),
739
- 'woocommerce_ac_email_page',
740
- 'ac_email_settings_section',
741
- array( 'Enter the name that should appear in the email sent.', 'woocommerce-abandoned-cart' )
742
  );
743
 
744
  add_settings_field(
745
- 'wcal_from_email',
746
- __( '"From" Address', 'woocommerce-abandoned-cart' ),
747
- array( $this, 'wcal_from_email_callback' ),
748
- 'woocommerce_ac_email_page',
749
- 'ac_email_settings_section',
750
- array( 'Email address from which the reminder emails should be sent.', 'woocommerce-abandoned-cart' )
751
  );
752
 
753
  add_settings_field(
754
- 'wcal_reply_email',
755
- __( 'Send Reply Emails to', 'woocommerce-abandoned-cart' ),
756
- array( $this, 'wcal_reply_email_callback' ),
757
- 'woocommerce_ac_email_page',
758
- 'ac_email_settings_section',
759
- array( 'When a contact receives your email and clicks reply, which email address should that reply be sent to?', 'woocommerce-abandoned-cart' )
760
  );
761
 
762
- // Finally, we register the fields with WordPress
763
  register_setting(
764
  'woocommerce_ac_settings',
765
  'wcal_enable_cart_emails'
@@ -768,13 +824,13 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
768
  register_setting(
769
  'woocommerce_ac_settings',
770
  'ac_lite_cart_abandoned_time',
771
- array ( $this, 'ac_lite_cart_time_validation' )
772
  );
773
 
774
  register_setting(
775
  'woocommerce_ac_settings',
776
  'ac_lite_delete_abandoned_order_days',
777
- array ( $this, 'wcal_delete_days_validation' )
778
  );
779
 
780
  register_setting(
@@ -810,7 +866,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
810
  register_setting(
811
  'woocommerce_ac_email_settings',
812
  'wcal_from_name'
813
- );
814
  register_setting(
815
  'woocommerce_ac_email_settings',
816
  'wcal_from_email'
@@ -820,62 +876,68 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
820
  'wcal_reply_email'
821
  );
822
 
823
- do_action ( "wcal_add_new_settings" );
824
  }
825
 
826
  /**
827
  * Settings API callback for section "ac_lite_general_settings_section".
 
828
  * @since 2.5
829
  */
830
- function ac_lite_general_options_callback() {
831
-
832
  }
833
 
834
  /**
835
- * Settings API callback for the enable cart reminder emails
 
 
836
  * @since 5.5
837
  */
838
  public static function wcal_enable_cart_emails_callback( $args ) {
839
 
840
- $enable_cart_emails = get_option( 'wcal_enable_cart_emails' );
841
 
842
- if (isset( $enable_cart_emails ) && $enable_cart_emails == "" ) {
843
  $enable_cart_emails = 'off';
844
  }
845
- $html = '<input type="checkbox" id="wcal_enable_cart_emails" name="wcal_enable_cart_emails" value="on" ' . checked( 'on', $enable_cart_emails, false ) . ' />';
846
- $html .= '<label for="wcal_enable_cart_emails"> ' . $args[0] . '</label>';
847
- echo $html;
 
 
848
  }
849
 
850
  /**
851
  * Settings API callback for cart time field.
852
- * @param array $args Arguments
 
853
  * @since 2.5
854
  */
855
- function ac_lite_cart_abandoned_time_callback( $args ) {
856
- // First, we read the option
857
  $cart_abandoned_time = get_option( 'ac_lite_cart_abandoned_time' );
858
- // Next, we update the name attribute to access this element's ID in the context of the display options array
859
- // We also access the show_header element of the options collection in the call to the checked() helper function
860
  printf(
861
- '<input type="text" id="ac_lite_cart_abandoned_time" name="ac_lite_cart_abandoned_time" value="%s" />',
862
- isset( $cart_abandoned_time ) ? esc_attr( $cart_abandoned_time ) : ''
863
- );
864
- // Here, we'll take the first argument of the array and add it to a label next to the checkbox
865
- $html = '<label for="ac_lite_cart_abandoned_time"> ' . $args[0] . '</label>';
866
- echo $html;
867
  }
868
 
869
  /**
870
  * Settings API cart time field validation.
871
- * @param int | string $input
872
- * @return int | string $output
 
873
  * @since 2.5
874
  */
875
- function ac_lite_cart_time_validation( $input ) {
876
  $output = '';
877
- if ( '' != $input && ( is_numeric( $input) && $input > 0 ) ) {
878
- $output = stripslashes( $input) ;
879
  } else {
880
  add_settings_error( 'ac_lite_cart_abandoned_time', 'error found', __( 'Abandoned cart cut off time should be numeric and has to be greater than 0.', 'woocommerce-abandoned-cart' ) );
881
  }
@@ -884,8 +946,9 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
884
 
885
  /**
886
  * Validation for automatically delete abandoned carts after X days.
887
- * @param int | string $input input of the field Abandoned cart cut off time
888
- * @return int | string $output Error message or the input value
 
889
  * @since 5.0
890
  */
891
  public static function wcal_delete_days_validation( $input ) {
@@ -900,214 +963,238 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
900
 
901
  /**
902
  * Callback for deleting abandoned order after X days field.
903
- * @param array $args Argument given while adding the field
 
904
  * @since 5.0
905
  */
906
  public static function wcal_delete_abandoned_orders_days_callback( $args ) {
907
- // First, we read the option
908
  $delete_abandoned_order_days = get_option( 'ac_lite_delete_abandoned_order_days' );
909
- // Next, we update the name attribute to access this element's ID in the context of the display options array
910
- // We also access the show_header element of the options collection in the call to the checked() helper function
911
  printf(
912
  '<input type="text" id="ac_lite_delete_abandoned_order_days" name="ac_lite_delete_abandoned_order_days" value="%s" />',
913
  isset( $delete_abandoned_order_days ) ? esc_attr( $delete_abandoned_order_days ) : ''
914
  );
915
- // Here, we'll take the first argument of the array and add it to a label next to the checkbox
916
  $html = '<label for="ac_lite_delete_abandoned_order_days"> ' . $args[0] . '</label>';
917
- echo $html;
918
  }
919
 
920
  /**
921
  * Settings API callback for email admin on cart recovery field.
922
- * @param array $args Arguments
 
923
  * @since 2.5
924
  */
925
- function ac_lite_email_admin_on_recovery( $args ) {
926
- // First, we read the option
927
  $email_admin_on_recovery = get_option( 'ac_lite_email_admin_on_recovery' );
928
 
929
  // This condition added to avoid the notie displyed while Check box is unchecked.
930
  if ( isset( $email_admin_on_recovery ) && '' == $email_admin_on_recovery ) {
931
  $email_admin_on_recovery = 'off';
932
  }
933
- // Next, we update the name attribute to access this element's ID in the context of the display options array
934
- // We also access the show_header element of the options collection in the call to the checked() helper function
935
- $html='';
936
  printf(
937
- '<input type="checkbox" id="ac_lite_email_admin_on_recovery" name="ac_lite_email_admin_on_recovery" value="on"
938
- ' . checked('on', $email_admin_on_recovery, false).' />'
939
  );
940
 
941
- // Here, we'll take the first argument of the array and add it to a label next to the checkbox
942
  $html .= '<label for="ac_lite_email_admin_on_recovery"> ' . $args[0] . '</label>';
943
- echo $html;
944
  }
 
945
  /**
946
  * Settings API callback for capturing guest cart which do not reach the checkout page.
947
- * @param array $args Arguments
 
948
  * @since 2.7
949
  */
950
- function wcal_track_guest_cart_from_cart_page_callback( $args ) {
951
- // First, we read the option
952
- $disable_guest_cart_from_cart_page = get_option( 'ac_lite_track_guest_cart_from_cart_page' );
953
 
954
  // This condition added to avoid the notice displyed while Check box is unchecked.
955
- if ( isset( $disable_guest_cart_from_cart_page ) && '' == $disable_guest_cart_from_cart_page ) {
956
  $disable_guest_cart_from_cart_page = 'off';
957
  }
958
- // Next, we update the name attribute to access this element's ID in the context of the display options array
959
- // We also access the show_header element of the options collection in the call to the checked() helper function
960
- $html = '';
961
 
962
  printf(
963
- '<input type="checkbox" id="ac_lite_track_guest_cart_from_cart_page" name="ac_lite_track_guest_cart_from_cart_page" value="on"
964
- '.checked( 'on', $disable_guest_cart_from_cart_page, false ) . ' />' );
965
- // Here, we'll take the first argument of the array and add it to a label next to the checkbox
 
966
  $html .= '<label for="ac_lite_track_guest_cart_from_cart_page"> ' . $args[0] . '</label>';
967
- echo $html;
968
  }
969
 
970
  /**
971
  * Call back function for guest user cart capture message
972
- * @param array $args Argument for adding field details
 
973
  * @since 7.8
974
  */
975
  public static function wcal_guest_cart_capture_msg_callback( $args ) {
976
 
977
  $guest_msg = get_option( 'wcal_guest_cart_capture_msg' );
978
 
979
- $html = "<textarea rows='4' cols='80' id='wcal_guest_cart_capture_msg' name='wcal_guest_cart_capture_msg'>" . htmlspecialchars( $guest_msg, ENT_QUOTES ) . "</textarea>";
 
 
980
 
981
- $html .= '<label for="wcal_guest_cart_capture_msg"> ' . $args[0] . '</label>';
982
- echo $html;
983
  }
984
 
985
  /**
986
  * Call back function for registered user cart capture message
987
- * @param array $args Argument for adding field details
 
988
  * @since 7.8
989
  */
990
  public static function wcal_logged_cart_capture_msg_callback( $args ) {
991
 
992
  $logged_msg = get_option( 'wcal_logged_cart_capture_msg' );
993
 
994
- $html = "<input type='text' id='wcal_logged_cart_capture_msg' name='wcal_logged_cart_capture_msg' value='" . htmlspecialchars( $logged_msg, ENT_QUOTES ) . "' style='width:60%;'/>";
 
 
995
 
996
- $html .= '<label for="wcal_logged_cart_capture_msg"> ' . $args[0] . '</label>';
997
- echo $html;
998
  }
999
 
1000
 
1001
  /**
1002
- * Text to allow the user the choice to opt out of cart tracking
 
 
1003
  * @since 5.5
1004
  */
1005
  public static function wcal_gdpr_allow_opt_out_callback( $args ) {
1006
-
1007
  $wcal_gdpr_allow_opt_out = get_option( 'wcal_gdpr_allow_opt_out' );
1008
-
1009
- $html = "<input type='text' class='regular-text' id='wcal_gdpr_allow_opt_out' name='wcal_gdpr_allow_opt_out' value='" . htmlspecialchars( $wcal_gdpr_allow_opt_out, ENT_QUOTES ) . "' />";
1010
-
1011
- $html .= '<label for="wcal_gdpr_allow_opt_out"> ' . $args[0] . '</label>';
1012
- echo $html;
 
 
1013
  }
1014
 
1015
  /**
1016
  * Message to display when the user chooses to opt out of cart tracking.
 
 
1017
  * @since 5.5
1018
  */
1019
  public static function wcal_gdpr_opt_out_msg_callback( $args ) {
1020
-
1021
  $wcal_gdpr_opt_out_message = get_option( 'wcal_gdpr_opt_out_message' );
1022
-
1023
- $html = "<input type='text' id='wcal_gdpr_opt_out_message' name='wcal_gdpr_opt_out_message' value='" . htmlspecialchars( $wcal_gdpr_opt_out_message, ENT_QUOTES ) . "' style='width:60%;'/>";
1024
-
1025
- $html .= '<label for="wcal_gdpr_opt_out_message"> ' . $args[0] . '</label>';
1026
- echo $html;
 
 
1027
  }
1028
 
1029
  /**
1030
  * Settings API callback for Abandoned cart email settings of the plugin.
 
1031
  * @since 3.5
1032
  */
1033
- function wcal_email_callback () {
1034
-
1035
  }
1036
 
1037
  /**
1038
  * Settings API callback for from name used in Abandoned cart email.
1039
- * @param array $args Arguments
 
1040
  * @since 3.5
1041
  */
1042
  public static function wcal_from_name_callback( $args ) {
1043
- // First, we read the option
1044
  $wcal_from_name = get_option( 'wcal_from_name' );
1045
- // Next, we update the name attribute to access this element's ID in the context of the display options array
1046
- // We also access the show_header element of the options collection in the call to the checked() helper function
1047
  printf(
1048
- '<input type="text" id="wcal_from_name" name="wcal_from_name" value="%s" />',
1049
- isset( $wcal_from_name ) ? esc_attr( $wcal_from_name ) : ''
1050
  );
1051
- // Here, we'll take the first argument of the array and add it to a label next to the checkbox
1052
- $html = '<label for="wcal_from_name_label"> ' . $args[0] . '</label>';
1053
- echo $html;
1054
  }
1055
 
1056
  /**
1057
  * Settings API callback for from email used in Abandoned cart email.
1058
- * @param array $args Arguments
 
1059
  * @since 3.5
1060
  */
1061
  public static function wcal_from_email_callback( $args ) {
1062
- // First, we read the option
1063
  $wcal_from_email = get_option( 'wcal_from_email' );
1064
- // Next, we update the name attribute to access this element's ID in the context of the display options array
1065
- // We also access the show_header element of the options collection in the call to the checked() helper function
1066
  printf(
1067
- '<input type="text" id="wcal_from_email" name="wcal_from_email" value="%s" />',
1068
- isset( $wcal_from_email ) ? esc_attr( $wcal_from_email ) : ''
1069
  );
1070
- // Here, we'll take the first argument of the array and add it to a label next to the checkbox
1071
- $html = '<label for="wcal_from_email_label"> ' . $args[0] . '</label>';
1072
- echo $html;
1073
  }
1074
 
1075
  /**
1076
  * Settings API callback for reply email used in Abandoned cart email.
1077
- * @param array $args Arguments
 
1078
  * @since 3.5
1079
  */
1080
  public static function wcal_reply_email_callback( $args ) {
1081
- // First, we read the option
1082
  $wcal_reply_email = get_option( 'wcal_reply_email' );
1083
- // Next, we update the name attribute to access this element's ID in the context of the display options array
1084
- // We also access the show_header element of the options collection in the call to the checked() helper function
1085
  printf(
1086
- '<input type="text" id="wcal_reply_email" name="wcal_reply_email" value="%s" />',
1087
- isset( $wcal_reply_email ) ? esc_attr( $wcal_reply_email ) : ''
1088
  );
1089
- // Here, we'll take the first argument of the array and add it to a label next to the checkbox
1090
- $html = '<label for="wcal_reply_email_label"> ' . $args[0] . '</label>';
1091
- echo $html;
1092
- }
1093
 
1094
  /**
1095
  * Add a submenu page under the WooCommerce.
 
1096
  * @hook admin_menu
1097
  * @since 1.0
1098
  */
1099
- function wcal_admin_menu() {
1100
- $page = add_submenu_page ( 'woocommerce', __( 'Abandoned Carts', 'woocommerce-abandoned-cart' ), __( 'Abandoned Carts', 'woocommerce-abandoned-cart' ), 'manage_woocommerce', 'woocommerce_ac_page', array( &$this, 'wcal_menu_page' ) );
1101
  }
1102
 
1103
  /**
1104
  * Capture the cart and insert the information of the cart into DataBase.
 
1105
  * @hook woocommerce_cart_updated
1106
  * @globals mixed $wpdb
1107
  * @globals mixed $woocommerce
1108
  * @since 1.0
1109
  */
1110
- function wcal_store_cart_timestamp() {
1111
 
1112
  $block_crawlers = apply_filters( 'wcal_block_crawlers', false );
1113
 
@@ -1131,7 +1218,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1131
  $cart_ignored = 0;
1132
  $recovered_cart = 0;
1133
 
1134
- $track_guest_user_cart_from_cart = "";
1135
  if ( isset( $track_guest_cart_from_cart_page ) ) {
1136
  $track_guest_user_cart_from_cart = $track_guest_cart_from_cart_page;
1137
  }
@@ -1145,175 +1232,228 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1145
 
1146
  if ( is_user_logged_in() ) {
1147
 
1148
- $user_id = get_current_user_id();
1149
  $gdpr_consent = get_user_meta( $user_id, 'wcal_gdpr_tracking_choice', true );
1150
 
1151
- if( $gdpr_consent === '' ) {
1152
  $gdpr_consent = true;
1153
  }
1154
 
1155
  $wcal_user_restricted = false;
1156
  $wcal_user_restricted = apply_filters( 'wcal_restrict_user', $wcal_user_restricted, $user_id );
1157
-
1158
- if( $gdpr_consent && ! $wcal_user_restricted ) {
1159
-
1160
- $query = "SELECT * FROM `".$wpdb->prefix."ac_abandoned_cart_history_lite`
1161
- WHERE user_id = %d
1162
- AND cart_ignored = %s
1163
- AND recovered_cart = %d ";
1164
- $results = $wpdb->get_results( $wpdb->prepare( $query, $user_id, $cart_ignored, $recovered_cart ) );
1165
 
1166
- if ( 0 == count( $results ) ) {
1167
- //$wcal_woocommerce_persistent_cart =version_compare( $woocommerce->version, '3.1.0', ">=" ) ? '_woocommerce_persistent_cart_' . get_current_blog_id() : '_woocommerce_persistent_cart' ;
1168
-
1169
- //$cart_info_meta = json_encode( get_user_meta( $user_id, $wcal_woocommerce_persistent_cart, true ) );
1170
 
 
 
 
 
 
 
 
 
 
1171
  $cart_info_meta = array();
1172
  $cart_info_meta['cart'] = WC()->session->cart;
1173
- $cart_info_meta = json_encode( $cart_info_meta );
1174
 
1175
- if( '' !== $cart_info_meta && '{"cart":[]}' != $cart_info_meta && '""' !== $cart_info_meta ) {
1176
  $cart_info = $cart_info_meta;
1177
- $user_type = "REGISTERED";
1178
- $insert_query = "INSERT INTO `".$wpdb->prefix."ac_abandoned_cart_history_lite`
1179
- ( user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type )
1180
- VALUES ( %d, %s, %d, %s, %s )";
1181
- $wpdb->query( $wpdb->prepare( $insert_query, $user_id, $cart_info,$current_time, $cart_ignored, $user_type ) );
1182
-
 
 
 
 
 
1183
  $abandoned_cart_id = $wpdb->insert_id;
1184
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
1185
  }
1186
  } elseif ( isset( $results[0]->abandoned_cart_time ) && $compare_time > $results[0]->abandoned_cart_time ) {
1187
- //$wcal_woocommerce_persistent_cart = version_compare( $woocommerce->version, '3.1.0', ">=" ) ? '_woocommerce_persistent_cart_' . get_current_blog_id() : '_woocommerce_persistent_cart' ;
1188
- //$updated_cart_info = json_encode( get_user_meta( $user_id, $wcal_woocommerce_persistent_cart, true ) );
1189
-
1190
  $updated_cart_info = array();
1191
  $updated_cart_info['cart'] = WC()->session->cart;
1192
- $updated_cart_info = json_encode( $updated_cart_info );
1193
 
1194
  if ( ! $this->wcal_compare_carts( $user_id, $results[0]->abandoned_cart_info ) ) {
1195
  $updated_cart_ignored = 1;
1196
- $query_ignored = "UPDATE `".$wpdb->prefix."ac_abandoned_cart_history_lite`
1197
- SET cart_ignored = %s
1198
- WHERE user_id = %d ";
1199
- $wpdb->query( $wpdb->prepare( $query_ignored, $updated_cart_ignored, $user_id ) );
1200
-
1201
- $user_type = "REGISTERED";
1202
- $query_update = "INSERT INTO `".$wpdb->prefix."ac_abandoned_cart_history_lite`
1203
- (user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type)
1204
- VALUES (%d, %s, %d, %s, %s)";
1205
- $wpdb->query( $wpdb->prepare( $query_update, $user_id, $updated_cart_info, $current_time, $cart_ignored, $user_type ) );
1206
-
1207
- update_user_meta ( $user_id, '_woocommerce_ac_modified_cart', md5( "yes" ) );
 
 
 
 
 
 
 
1208
 
1209
- $abandoned_cart_id = $wpdb->insert_id;
1210
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
1211
  } else {
1212
- update_user_meta ( $user_id, '_woocommerce_ac_modified_cart', md5( "no" ) );
1213
  }
1214
  } else {
1215
- //$wcal_woocommerce_persistent_cart = version_compare( $woocommerce->version, '3.1.0', ">=" ) ? '_woocommerce_persistent_cart_' . get_current_blog_id() : '_woocommerce_persistent_cart' ;
1216
- //$updated_cart_info = json_encode( get_user_meta( $user_id, $wcal_woocommerce_persistent_cart, true ) );
1217
-
1218
  $updated_cart_info = array();
1219
  $updated_cart_info['cart'] = WC()->session->cart;
1220
- $updated_cart_info = json_encode( $updated_cart_info );
1221
-
1222
- $query_update = "UPDATE `".$wpdb->prefix."ac_abandoned_cart_history_lite`
1223
- SET abandoned_cart_info = %s,
1224
- abandoned_cart_time = %d
1225
- WHERE user_id = %d
1226
- AND cart_ignored = %s ";
1227
- $wpdb->query( $wpdb->prepare( $query_update, $updated_cart_info, $current_time, $user_id, $cart_ignored ) );
1228
-
1229
- $query_update = "SELECT * FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE user_id ='" . $user_id . "' AND cart_ignored='0' ";
1230
- $get_abandoned_record = $wpdb->get_results( $query_update );
 
 
 
 
 
 
 
 
1231
 
1232
  if ( count( $get_abandoned_record ) > 0 ) {
1233
- $abandoned_cart_id = $get_abandoned_record[0]->id;
1234
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
1235
  }
1236
  }
1237
  }
1238
  } else {
1239
- //start here guest user
1240
  $user_id = wcal_common::wcal_get_cart_session( 'user_id' );
1241
 
1242
  // GDPR consent.
1243
- $gdpr_consent = true;
1244
  $show_gdpr_msg = wcal_common::wcal_get_cart_session( 'wcal_cart_tracking_refused' );
1245
  if ( isset( $show_gdpr_msg ) && 'yes' === $show_gdpr_msg ) {
1246
  $gdpr_consent = false;
1247
  }
1248
 
1249
  if ( $gdpr_consent ) {
1250
- $query = "SELECT * FROM `".$wpdb->prefix."ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = '0' AND recovered_cart = '0' AND user_id != '0'";
1251
- $results = $wpdb->get_results( $wpdb->prepare( $query, $user_id ) );
 
 
 
 
 
 
 
1252
  $cart = array();
1253
 
1254
  $get_cookie = WC()->session->get_customer_id();
1255
 
1256
- if ( function_exists('WC') ) {
1257
  $cart['cart'] = WC()->session->cart;
1258
  } else {
1259
  $cart['cart'] = $woocommerce->session->cart;
1260
  }
1261
 
1262
- $updated_cart_info = json_encode( $cart );
1263
- //$updated_cart_info = addslashes ( $updated_cart_info );
1264
 
1265
  if ( count( $results ) > 0 && '{"cart":[]}' != $updated_cart_info ) {
1266
  if ( $compare_time > $results[0]->abandoned_cart_time ) {
1267
  if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {
1268
 
1269
- $query_ignored = "UPDATE `".$wpdb->prefix."ac_abandoned_cart_history_lite`
1270
- SET cart_ignored = '1'
1271
- WHERE user_id ='".$user_id."'";
1272
- $wpdb->query( $query_ignored );
1273
-
1274
- $user_type = 'GUEST';
1275
- $query_update = "INSERT INTO `".$wpdb->prefix."ac_abandoned_cart_history_lite`
1276
- (user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type)
1277
- VALUES (%d, %s, %d, %s, %s)";
1278
- $wpdb->query( $wpdb->prepare( $query_update, $user_id, $updated_cart_info, $current_time, $cart_ignored, $user_type ) );
1279
- update_user_meta( $user_id, '_woocommerce_ac_modified_cart', md5("yes") );
 
 
 
 
 
 
 
 
1280
  } else {
1281
- update_user_meta( $user_id, '_woocommerce_ac_modified_cart', md5("no") );
1282
  }
1283
  } else {
1284
- $query_update = "UPDATE `".$wpdb->prefix."ac_abandoned_cart_history_lite`
1285
- SET abandoned_cart_info = '".$updated_cart_info."', abandoned_cart_time = '".$current_time."'
1286
- WHERE user_id='".$user_id."' AND cart_ignored='0' ";
1287
- $wpdb->query( $query_update );
 
 
 
 
 
1288
  }
1289
  } else {
1290
- /**
1291
- * Here we capture the guest cart from the cart page.
1292
- * @since 3.5
1293
- */
1294
- if ( 'on' == $track_guest_user_cart_from_cart && isset( $get_cookie ) && '' != $get_cookie ) {
1295
- $query = "SELECT * FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE session_id LIKE %s AND cart_ignored = '0' AND recovered_cart = '0' ";
1296
- $results = $wpdb->get_results( $wpdb->prepare( $query, $get_cookie ) );
 
 
 
1297
  if ( 0 == count( $results ) ) {
1298
  $cart_info = $updated_cart_info;
1299
  $blank_cart_info = '[]';
1300
  if ( $blank_cart_info != $cart_info && '{"cart":[]}' != $cart_info ) {
1301
- $insert_query = "INSERT INTO `" . $wpdb->prefix . "ac_abandoned_cart_history_lite`
1302
- ( abandoned_cart_info , abandoned_cart_time , cart_ignored , recovered_cart, user_type, session_id )
1303
- VALUES ( '" . $cart_info."' , '" . $current_time . "' , '0' , '0' , 'GUEST', '". $get_cookie ."' )";
1304
- $wpdb->query( $insert_query );
 
 
 
 
 
 
 
1305
  $abandoned_cart_id = $wpdb->insert_id;
1306
  }
1307
  } elseif ( $compare_time > $results[0]->abandoned_cart_time ) {
1308
  $blank_cart_info = '[]';
1309
  if ( $blank_cart_info != $updated_cart_info && '{"cart":[]}' != $updated_cart_info ) {
1310
  if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {
1311
- $query_ignored = "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET cart_ignored = '1' WHERE session_id ='" . $get_cookie . "'";
1312
- $wpdb->query( $query_ignored );
1313
- $query_update = "INSERT INTO `" . $wpdb->prefix . "ac_abandoned_cart_history_lite`
1314
- ( abandoned_cart_info, abandoned_cart_time, cart_ignored, recovered_cart, user_type, session_id )
1315
- VALUES ( '" . $updated_cart_info . "', '" . $current_time . "', '0', '0', 'GUEST', '". $get_cookie ."' )";
1316
- $wpdb->query( $query_update );
 
 
 
 
 
 
 
 
 
 
 
 
1317
  $abandoned_cart_id = $wpdb->insert_id;
1318
  }
1319
  }
@@ -1321,13 +1461,20 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1321
  $blank_cart_info = '[]';
1322
  if ( $blank_cart_info != $updated_cart_info && '{"cart":[]}' != $updated_cart_info ) {
1323
  if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {
1324
- $query_update = "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` SET abandoned_cart_info = '" . $updated_cart_info . "', abandoned_cart_time = '" . $current_time . "' WHERE session_id ='" . $get_cookie . "' AND cart_ignored='0' ";
1325
- $wpdb->query( $query_update );
 
 
 
 
 
 
 
1326
  }
1327
  }
1328
  }
1329
- if( isset( $abandoned_cart_id ) ) {
1330
- // add the abandoned id in the session
1331
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
1332
  }
1333
  }
@@ -1336,21 +1483,27 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1336
  }
1337
  }
1338
 
1339
- public function wcal_detect_crawlers( $ignore ){
1340
- $user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
 
 
 
 
 
 
1341
 
1342
  if ( '' === $user_agent ) {
1343
  return $ignore;
1344
  }
1345
 
1346
  // Current list of bots being blocked:
1347
- // 1. Googlebot, BingBot, DuckDuckBot, YandexBot, Exabot
1348
- // 2. cURL
1349
- // 3. wget
1350
- // 4. Yahoo/Slurp
1351
- // 5. Baiduspider
1352
- // 6. Sogou
1353
- // 7. Alexa
1354
  $bot_agents = array(
1355
  'curl',
1356
  'wget',
@@ -1362,8 +1515,8 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1362
  'ia_archiver',
1363
  );
1364
 
1365
- foreach( $bot_agents as $url) {
1366
- if ( stripos( $user_agent, $url ) !== false ) {
1367
  return true;
1368
  }
1369
  }
@@ -1373,131 +1526,163 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1373
 
1374
  /**
1375
  * It will unsubscribe the abandoned cart, so user will not recieve further abandoned cart emails.
 
1376
  * @hook template_include
1377
- * @param string $args Arguments
1378
- * @return string $args
1379
  * @globals mixed $wpdb
1380
  * @since 2.9
1381
  */
1382
- function wcal_email_unsubscribe( $args ) {
1383
  global $wpdb;
1384
 
1385
- if ( isset( $_GET['wcal_track_unsubscribe'] ) && $_GET['wcal_track_unsubscribe'] == 'wcal_unsubscribe' ) {
1386
- $encoded_email_id = rawurldecode( $_GET['validate'] );
1387
- $validate_email_id_string = str_replace( " " , "+", $encoded_email_id );
1388
  $validate_email_address_string = '';
1389
  $validate_email_id_decode = 0;
1390
- $cryptKey = get_option( 'wcal_security_key' );
1391
- $validate_email_id_decode = Wcal_Aes_Ctr::decrypt( $validate_email_id_string, $cryptKey, 256 );
1392
- if ( isset( $_GET['track_email_id'] ) ) {
1393
- $encoded_email_address = rawurldecode( $_GET['track_email_id'] );
1394
- $validate_email_address_string = str_replace( " " , "+", $encoded_email_address );
1395
  }
1396
- $query_id = "SELECT * FROM `" . $wpdb->prefix . "ac_sent_history_lite` WHERE id = %d ";
1397
- $results_sent = $wpdb->get_results ( $wpdb->prepare( $query_id, $validate_email_id_decode ) );
 
 
 
 
 
1398
  $email_address = '';
1399
  if ( isset( $results_sent[0] ) ) {
1400
- $email_address = $results_sent[0]->sent_email_id;
1401
  }
1402
- if ( $validate_email_address_string == hash( 'sha256', $email_address ) && '' != $email_address ) {
1403
  $email_sent_id = $validate_email_id_decode;
1404
- $get_ac_id_query = "SELECT abandoned_order_id FROM `" . $wpdb->prefix . "ac_sent_history_lite` WHERE id = %d";
1405
- $get_ac_id_results = $wpdb->get_results( $wpdb->prepare( $get_ac_id_query , $email_sent_id ) );
 
 
 
 
1406
  $user_id = 0;
1407
  if ( isset( $get_ac_id_results[0] ) ) {
1408
- $get_user_id_query = "SELECT user_id FROM `" . $wpdb->prefix . "ac_abandoned_cart_history_lite` WHERE id = %d";
1409
- $get_user_results = $wpdb->get_results( $wpdb->prepare( $get_user_id_query , $get_ac_id_results[0]->abandoned_order_id ) );
 
 
 
 
1410
  }
1411
  if ( isset( $get_user_results[0] ) ) {
1412
  $user_id = $get_user_results[0]->user_id;
1413
  }
1414
 
1415
- $unsubscribe_query = "UPDATE `" . $wpdb->prefix . "ac_abandoned_cart_history_lite`
1416
- SET unsubscribe_link = '1'
1417
- WHERE user_id= %d AND cart_ignored='0' ";
1418
- $wpdb->query( $wpdb->prepare( $unsubscribe_query , $user_id ) );
1419
- echo "Unsubscribed Successfully";
 
 
 
 
1420
  sleep( 2 );
1421
  $url = get_option( 'siteurl' );
1422
  ?>
1423
  <script>
1424
- location.href = "<?php echo $url; ?>";
1425
  </script>
1426
- <?php
1427
  }
1428
  } else {
1429
- return $args;
1430
  }
1431
  }
1432
 
1433
  /**
1434
  * It will track the URL of cart link from email, and it will populate the logged-in and guest users cart.
 
1435
  * @hook template_include
1436
- * @param string $template
1437
- * @return string $template
1438
  * @globals mixed $wpdb
1439
  * @globals mixed $woocommerce
1440
  * @since 1.0
1441
  */
1442
- function wcal_email_track_links( $template ) {
1443
  global $woocommerce;
1444
- $track_link = '';
1445
 
1446
- if ( isset( $_GET['wcal_action'] ) ) {
1447
- $track_link = $_GET['wcal_action'];
1448
- }
1449
- if ( $track_link == 'track_links' ) {
1450
  if ( '' === session_id() ) {
1451
- //session has not started
1452
  session_start();
1453
  }
1454
  global $wpdb;
1455
- $validate_server_string = rawurldecode( $_GET ['validate'] );
1456
- $validate_server_string = str_replace( " " , "+", $validate_server_string );
1457
  $validate_encoded_string = $validate_server_string;
1458
- $cryptKey = get_option( 'wcal_security_key' );
1459
- $link_decode = Wcal_Aes_Ctr::decrypt( $validate_encoded_string, $cryptKey, 256 );
1460
  $sent_email_id_pos = strpos( $link_decode, '&' );
1461
- $email_sent_id = substr( $link_decode , 0, $sent_email_id_pos );
1462
 
1463
  wcal_common::wcal_set_cart_session( 'email_sent_id', $email_sent_id );
1464
  set_transient( 'wcal_email_sent_id', $email_sent_id, 5 );
1465
 
1466
- $url_pos = strpos( $link_decode, '=' );
1467
- $url_pos = $url_pos + 1;
1468
- $url = substr( $link_decode, $url_pos );
1469
- $get_ac_id_query = "SELECT abandoned_order_id FROM `".$wpdb->prefix."ac_sent_history_lite` WHERE id = %d";
1470
- $get_ac_id_results = $wpdb->get_results( $wpdb->prepare( $get_ac_id_query, $email_sent_id ) );
 
 
 
 
1471
 
1472
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $get_ac_id_results[0]->abandoned_order_id );
1473
  set_transient( 'wcal_abandoned_id', $get_ac_id_results[0]->abandoned_order_id, 5 );
1474
 
1475
- $get_user_results = array();
1476
  if ( count( $get_ac_id_results ) > 0 ) {
1477
- $get_user_id_query = "SELECT user_id FROM `".$wpdb->prefix."ac_abandoned_cart_history_lite` WHERE id = %d";
1478
- $get_user_results = $wpdb->get_results( $wpdb->prepare( $get_user_id_query, $get_ac_id_results[0]->abandoned_order_id ) );
1479
- }
1480
- $user_id = 0;
1481
- if ( isset( $get_user_results ) && count( $get_user_results ) > 0 ) {
1482
- $user_id = $get_user_results[0]->user_id;
1483
  }
1484
- if ( 0 == $user_id ) {
1485
- echo "Link expired";
 
 
1486
  exit;
1487
  }
1488
  $user = wp_set_current_user( $user_id );
1489
- if ( $user_id >= "63000000" ) {
1490
- $query_guest = "SELECT * from `". $wpdb->prefix."ac_guest_abandoned_cart_history_lite` WHERE id = %d";
1491
- $results_guest = $wpdb->get_results( $wpdb->prepare( $query_guest, $user_id ) );
1492
- $query_cart = "SELECT recovered_cart FROM `".$wpdb->prefix."ac_abandoned_cart_history_lite` WHERE user_id = %d";
1493
- $results = $wpdb->get_results( $wpdb->prepare( $query_cart, $user_id ) );
1494
- if ( $results_guest && $results[0]->recovered_cart == '0' ) {
 
 
 
 
 
 
 
 
 
1495
  wcal_common::wcal_set_cart_session( 'guest_first_name', $results_guest[0]->billing_first_name );
1496
  wcal_common::wcal_set_cart_session( 'guest_last_name', $results_guest[0]->billing_last_name );
1497
  wcal_common::wcal_set_cart_session( 'guest_email', $results_guest[0]->email_id );
1498
  wcal_common::wcal_set_cart_session( 'user_id', $user_id );
1499
  } else {
1500
- if ( version_compare( $woocommerce->version, '3.0.0', ">=" ) ) {
1501
  wp_safe_redirect( get_permalink( wc_get_page_id( 'shop' ) ) );
1502
  exit;
1503
  } else {
@@ -1507,38 +1692,49 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1507
  }
1508
  }
1509
 
1510
- if ( $user_id < "63000000" ) {
1511
  $user_login = $user->data->user_login;
1512
  wp_set_auth_cookie( $user_id );
1513
- $my_temp = wc_load_persistent_cart( $user_login, $user );
1514
  do_action( 'wp_login', $user_login, $user );
1515
  if ( isset( $sign_in ) && is_wp_error( $sign_in ) ) {
1516
- echo $sign_in->get_error_message();
1517
  exit;
1518
  }
1519
- } else
1520
  $my_temp = $this->wcal_load_guest_persistent_cart( $user_id );
 
1521
 
1522
  if ( $email_sent_id > 0 && is_numeric( $email_sent_id ) ) {
1523
  wp_safe_redirect( $url );
1524
  exit;
1525
  }
1526
- } else
1527
  return $template;
 
1528
  }
1529
 
1530
  /**
1531
  * When customer clicks on the abandoned cart link and that cart is for the the guest users the it will load the guest
1532
  * user's cart detail.
 
1533
  * @globals mixed $woocommerce
1534
  * @since 1.0
1535
  */
1536
- function wcal_load_guest_persistent_cart() {
1537
  if ( wcal_common::wcal_get_cart_session( 'user_id' ) != '' ) {
1538
  global $woocommerce;
1539
- $saved_cart = json_decode( get_user_meta( wcal_common::wcal_get_cart_session( 'user_id' ), '_woocommerce_persistent_cart',true ), true );
1540
- $c = array();
1541
- $cart_contents_total = $cart_contents_weight = $cart_contents_count = $cart_contents_tax = $total = $subtotal = $subtotal_ex_tax = $tax_total = 0;
 
 
 
 
 
 
 
 
1542
  if ( count( $saved_cart ) > 0 ) {
1543
  foreach ( $saved_cart as $key => $value ) {
1544
  foreach ( $value as $a => $b ) {
@@ -1559,13 +1755,13 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1559
  $subtotal = $subtotal + $b['line_subtotal'];
1560
  $subtotal_ex_tax = $subtotal_ex_tax + $b['line_subtotal'];
1561
  }
1562
- $saved_cart_data[ $key ] = $value_new;
1563
- $woocommerce_cart_hash = $a;
1564
  }
1565
  }
1566
 
1567
  if ( $saved_cart ) {
1568
- if ( empty( $woocommerce->session->cart ) || ! is_array( $woocommerce->session->cart ) || sizeof( $woocommerce->session->cart ) == 0 ) {
1569
  $woocommerce->session->cart = $saved_cart['cart'];
1570
  $woocommerce->session->cart_contents_total = $cart_contents_total;
1571
  $woocommerce->session->cart_contents_weight = $cart_contents_weight;
@@ -1594,50 +1790,51 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1594
 
1595
  /**
1596
  * It will compare only guest users cart while capturing the cart.
1597
- * @param json_encode $new_cart New abandoned cart details
1598
- * @param json_encode $last_abandoned_cart Old abandoned cart details
1599
- * @return boolean true | false
 
1600
  * @since 1.0
1601
  */
1602
- function wcal_compare_only_guest_carts( $new_cart, $last_abandoned_cart ) {
1603
  $current_woo_cart = array();
1604
  $current_woo_cart = json_decode( stripslashes( $new_cart ), true );
1605
  $abandoned_cart_arr = array();
1606
  $abandoned_cart_arr = json_decode( $last_abandoned_cart, true );
1607
- $temp_variable = "";
1608
  if ( isset( $current_woo_cart['cart'] ) && isset( $abandoned_cart_arr['cart'] ) ) {
1609
- if ( count( $current_woo_cart['cart'] ) >= count( $abandoned_cart_arr['cart'] ) ) {
1610
- //do nothing
1611
  } else {
1612
  $temp_variable = $current_woo_cart;
1613
  $current_woo_cart = $abandoned_cart_arr;
1614
  $abandoned_cart_arr = $temp_variable;
1615
  }
1616
  if ( is_array( $current_woo_cart ) || is_object( $current_woo_cart ) ) {
1617
- foreach( $current_woo_cart as $key => $value ) {
1618
- foreach( $value as $item_key => $item_value ) {
1619
  $current_cart_product_id = $item_value['product_id'];
1620
  $current_cart_variation_id = $item_value['variation_id'];
1621
  $current_cart_quantity = $item_value['quantity'];
1622
 
1623
- if ( isset( $abandoned_cart_arr[$key][$item_key]['product_id'] ) ){
1624
- $abandoned_cart_product_id = $abandoned_cart_arr[$key][$item_key]['product_id'];
1625
  } else {
1626
- $abandoned_cart_product_id = "";
1627
  }
1628
- if ( isset( $abandoned_cart_arr[$key][$item_key]['variation_id'] ) ) {
1629
- $abandoned_cart_variation_id = $abandoned_cart_arr[$key][$item_key]['variation_id'];
1630
  } else {
1631
- $abandoned_cart_variation_id = "";
1632
  }
1633
- if ( isset( $abandoned_cart_arr[$key][$item_key]['quantity'] ) ) {
1634
- $abandoned_cart_quantity = $abandoned_cart_arr[$key][$item_key]['quantity'];
1635
  } else {
1636
- $abandoned_cart_quantity = "";
1637
  }
1638
- if ( ( $current_cart_product_id != $abandoned_cart_product_id ) ||
1639
  ( $current_cart_variation_id != $abandoned_cart_variation_id ) ||
1640
- ( $current_cart_quantity != $abandoned_cart_quantity ) ) {
1641
  return false;
1642
  }
1643
  }
@@ -1649,22 +1846,23 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1649
 
1650
  /**
1651
  * It will compare only loggedin users cart while capturing the cart.
1652
- * @param int | string $user_id User id
1653
- * @param json_encode $last_abandoned_cart Old abandoned cart details
1654
- * @return boolean true | false
 
1655
  * @since 1.0
1656
  */
1657
- function wcal_compare_carts( $user_id, $last_abandoned_cart ) {
1658
  global $woocommerce;
1659
- $current_woo_cart = array();
1660
- $abandoned_cart_arr = array();
1661
- $wcal_woocommerce_persistent_cart =version_compare( $woocommerce->version, '3.1.0', ">=" ) ? '_woocommerce_persistent_cart_' . get_current_blog_id() : '_woocommerce_persistent_cart' ;
1662
- $current_woo_cart = get_user_meta( $user_id, $wcal_woocommerce_persistent_cart, true );
1663
- $abandoned_cart_arr = json_decode( $last_abandoned_cart, true );
1664
- $temp_variable = "";
1665
  if ( isset( $current_woo_cart['cart'] ) && isset( $abandoned_cart_arr['cart'] ) ) {
1666
- if ( count( $current_woo_cart['cart'] ) >= count( $abandoned_cart_arr['cart'] ) ) {
1667
- //do nothing
1668
  } else {
1669
  $temp_variable = $current_woo_cart;
1670
  $current_woo_cart = $abandoned_cart_arr;
@@ -1678,25 +1876,24 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1678
  $current_cart_variation_id = $item_value['variation_id'];
1679
  $current_cart_quantity = $item_value['quantity'];
1680
 
1681
- if ( isset( $abandoned_cart_arr[$key][$item_key]['product_id'] ) ) {
1682
- $abandoned_cart_product_id = $abandoned_cart_arr[$key][$item_key]['product_id'];
1683
  } else {
1684
- $abandoned_cart_product_id = "";
1685
  }
1686
- if ( isset( $abandoned_cart_arr[$key][$item_key]['variation_id'] ) ) {
1687
- $abandoned_cart_variation_id = $abandoned_cart_arr[$key][$item_key]['variation_id'];
1688
  } else {
1689
- $abandoned_cart_variation_id = "";
1690
  }
1691
- if ( isset( $abandoned_cart_arr[$key][$item_key]['quantity'] ) ) {
1692
- $abandoned_cart_quantity = $abandoned_cart_arr[$key][$item_key]['quantity'];
1693
  } else {
1694
- $abandoned_cart_quantity = "";
1695
  }
1696
  if ( ( $current_cart_product_id != $abandoned_cart_product_id ) ||
1697
  ( $current_cart_variation_id != $abandoned_cart_variation_id ) ||
1698
- ( $current_cart_quantity != $abandoned_cart_quantity ) )
1699
- {
1700
  return false;
1701
  }
1702
  }
@@ -1708,14 +1905,15 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1708
 
1709
  /**
1710
  * It will add the wp editor for email body on the email edit page.
 
1711
  * @hook admin_init
1712
  * @since 2.6
1713
  */
1714
- function wcal_action_admin_init() {
1715
 
1716
- // only hook up these filters if we're in the admin panel and the current user has permission
1717
- // to edit posts and pages
1718
- if ( ! isset( $_GET['page'] ) || $_GET['page'] != "woocommerce_ac_page" ) {
1719
  return;
1720
  }
1721
  if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
@@ -1723,43 +1921,46 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1723
  }
1724
  if ( 'true' == get_user_option( 'rich_editing' ) ) {
1725
  remove_filter( 'the_excerpt', 'wpautop' );
1726
- add_filter( 'tiny_mce_before_init', array( &$this, 'wcal_format_tiny_MCE' ) );
1727
- add_filter( 'mce_buttons', array( &$this, 'wcal_filter_mce_button' ) );
1728
- add_filter( 'mce_external_plugins', array( &$this, 'wcal_filter_mce_plugin' ) );
1729
  }
1730
  }
1731
 
1732
  /**
1733
  * It will create a button on the WordPress editor.
 
1734
  * @hook mce_buttons
1735
- * @param array $buttons
1736
- * @return array $buttons
1737
  * @since 2.6
1738
  */
1739
- function wcal_filter_mce_button( $buttons ) {
1740
- // add a separation before our button, here our button's id is &quot;mygallery_button&quot;
1741
  array_push( $buttons, 'abandoncart', '|' );
1742
  return $buttons;
1743
  }
1744
 
1745
  /**
1746
  * It will add the list for the added extra button.
 
1747
  * @hook mce_external_plugins
1748
- * @param array $plugins
1749
- * @return array $plugins
1750
  * @since 2.6
1751
  */
1752
- function wcal_filter_mce_plugin( $plugins ) {
1753
- // this plugin file will work the magic of our button
1754
  $plugins['abandoncart'] = plugin_dir_url( __FILE__ ) . 'assets/js/abandoncart_plugin_button.js';
1755
  return $plugins;
1756
  }
1757
 
1758
  /**
1759
  * It will add the tabs on the Abandoned cart page.
 
1760
  * @since 1.0
1761
  */
1762
- function wcal_display_tabs() {
1763
 
1764
  $action = '';
1765
  $active_listcart = '';
@@ -1768,14 +1969,14 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1768
  $active_stats = '';
1769
  $active_dash = '';
1770
 
1771
- if( isset( $_GET[ 'action' ] ) ) {
1772
- $action = $_GET[ 'action' ];
1773
  } else {
1774
  $action = '';
1775
  $action = apply_filters( 'wcal_default_tab', $action );
1776
  }
1777
-
1778
- switch( $action ) {
1779
  case '':
1780
  case 'dashboard':
1781
  $active_dash = 'nav-tab-active';
@@ -1799,15 +2000,51 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1799
  }
1800
 
1801
  ?>
1802
- <div style="background-image: url('<?php echo plugins_url(); ?>/woocommerce-abandoned-cart/assets/images/ac_tab_icon.png') !important;" class="icon32"><br>
1803
  </div>
1804
  <h2 class="nav-tab-wrapper woo-nav-tab-wrapper">
1805
- <a href="admin.php?page=woocommerce_ac_page&action=dashboard" class="nav-tab <?php if ( isset( $active_dash ) ) echo $active_dash; ?>"> <?php _e( 'Dashboard', 'woocommerce-abandoned-cart' );?> </a>
1806
- <a href="admin.php?page=woocommerce_ac_page&action=listcart" class="nav-tab <?php if ( isset( $active_listcart ) ) echo $active_listcart; ?>"> <?php _e( 'Abandoned Orders', 'woocommerce-abandoned-cart' );?> </a>
1807
- <a href="admin.php?page=woocommerce_ac_page&action=emailtemplates" class="nav-tab <?php if ( isset( $active_emailtemplates ) ) echo $active_emailtemplates; ?>"> <?php _e( 'Email Templates', 'woocommerce-abandoned-cart' );?> </a>
1808
- <a href="admin.php?page=woocommerce_ac_page&action=emailsettings" class="nav-tab <?php if ( isset( $active_settings ) ) echo $active_settings; ?>"> <?php _e( 'Settings', 'woocommerce-abandoned-cart' );?> </a>
1809
- <a href="admin.php?page=woocommerce_ac_page&action=stats" class="nav-tab <?php if ( isset( $active_stats ) ) echo $active_stats; ?>"> <?php _e( 'Recovered Orders', 'woocommerce-abandoned-cart' );?> </a>
1810
- <a href="admin.php?page=woocommerce_ac_page&action=report" class="nav-tab <?php if ( isset( $active_report ) ) echo $active_report; ?>"> <?php _e( 'Product Report', 'woocommerce-abandoned-cart' );?> </a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1811
 
1812
  <?php do_action( 'wcal_add_settings_tab' ); ?>
1813
  </h2>
@@ -1816,46 +2053,40 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1816
 
1817
  /**
1818
  * It will add the scripts needed for the plugin.
 
1819
  * @hook admin_enqueue_scripts
1820
- * @param string $hook Name of hook
1821
  * @since 1.0
1822
  */
1823
- function wcal_enqueue_scripts_js( $hook ) {
1824
  global $pagenow, $woocommerce;
1825
- $page = isset( $_GET['page'] ) ? $_GET['page'] : '';
1826
- $action = isset( $_GET['action'] ) ? $_GET['action'] : '';
1827
 
1828
- if ( $page === '' || $page !== 'woocommerce_ac_page' ) {
1829
  return;
1830
  } else {
1831
  wp_enqueue_script( 'jquery' );
 
 
 
1832
  wp_enqueue_script(
1833
- 'jquery-ui-min',
1834
- plugins_url( '/assets/js/jquery-ui.min.js', __FILE__ ),
1835
- '',
1836
  '',
 
1837
  false
1838
  );
1839
- wp_enqueue_script( 'jquery-ui-datepicker' );
1840
- wp_enqueue_script(
1841
- 'jquery-tip',
1842
- plugins_url( '/assets/js/jquery.tipTip.minified.js', __FILE__ ),
1843
- '',
1844
- '',
1845
- false
1846
- );
1847
-
1848
-
1849
- wp_register_script( 'woocommerce_admin', plugins_url() . '/woocommerce/assets/js/admin/woocommerce_admin.min.js', array( 'jquery', 'jquery-tiptip' ) );
1850
- wp_register_script( 'woocommerce_tip_tap', plugins_url() . '/woocommerce/assets/js/jquery-tiptip/jquery.tipTip.min.js', array( 'jquery') );
1851
- wp_enqueue_script( 'woocommerce_tip_tap');
1852
  wp_enqueue_script( 'woocommerce_admin');
1853
  $locale = localeconv();
1854
  $decimal = isset( $locale['decimal_point'] ) ? $locale['decimal_point'] : '.';
1855
  $params = array(
1856
- /* translators: %s: decimal */
1857
  'i18n_decimal_error' => sprintf( __( 'Please enter in decimal (%s) format without thousand separators.', 'woocommerce' ), $decimal ),
1858
- /* translators: %s: price decimal separator */
1859
  'i18n_mon_decimal_error' => sprintf( __( 'Please enter in monetary decimal (%s) format without thousand separators and currency symbols.', 'woocommerce' ), wc_get_price_decimal_separator() ),
1860
  'i18n_country_iso_error' => __( 'Please enter in country code with two capital letters.', 'woocommerce' ),
1861
  'i18_sale_less_than_regular_error' => __( 'Please enter in a value less than the regular price.', 'woocommerce' ),
@@ -1870,12 +2101,11 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1870
  'export_products' => esc_url_raw( admin_url( 'edit.php?post_type=product&page=product_exporter' ) ),
1871
  ),
1872
  );
1873
- /**
1874
- * If we dont localize this script then from the WooCommerce check it will not run the javascript further and tooltip wont show any data.
1875
- * Also, we need above all parameters for the WooCoomerce js file. So we have taken it from the WooCommerce.
1876
- * @since: 5.1.2
1877
- */
1878
  wp_localize_script( 'woocommerce_admin', 'woocommerce_admin', $params );
 
1879
  ?>
1880
  <script type="text/javascript" >
1881
  function wcal_activate_email_template( template_id, active_state ) {
@@ -1883,37 +2113,65 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1883
  }
1884
  </script>
1885
  <?php
1886
- $js_src = includes_url('js/tinymce/') . 'tinymce.min.js';
1887
- wp_enqueue_script( 'tinyMce_ac',$js_src );
1888
- wp_enqueue_script( 'ac_email_variables', plugins_url() . '/woocommerce-abandoned-cart/assets/js/abandoncart_plugin_button.js' );
1889
- wp_enqueue_script( 'wcal_activate_template', plugins_url() . '/woocommerce-abandoned-cart/assets/js/wcal_template_activate.js' );
1890
-
1891
- // needed only on the dashboard page
1892
- if( 'woocommerce_ac_page' === $page && ( '' === $action || 'dashboard' === $action ) ) {
1893
- wp_register_script( 'jquery-ui-datepicker', plugins_url() . '/woocommerce/assets/js/admin/ui-datepicker.js' );
 
 
 
 
 
 
 
 
 
 
 
 
1894
  wp_enqueue_script( 'jquery-ui-datepicker' );
1895
 
1896
- wp_enqueue_script (
1897
- 'bootstrap_js',
1898
- plugins_url() . '/woocommerce-abandoned-cart/assets/js/admin/bootstrap.min.js',
1899
- '',
1900
- '',
1901
- false );
 
1902
 
1903
- wp_enqueue_script (
1904
  'reports_js',
1905
- plugins_url() . '/woocommerce-abandoned-cart/assets/js/admin/wcal_adv_dashboard.min.js',
1906
- '',
1907
  '',
 
1908
  false
1909
  );
1910
  }
1911
- // needed only on the abandoned orders page
1912
- wp_enqueue_script( 'wcal_abandoned_cart_details', plugins_url() . '/woocommerce-abandoned-cart/assets/js/admin/wcal_abandoned_cart_detail_modal.min.js' );
 
 
 
 
 
 
1913
 
1914
- wp_enqueue_script( 'wcal_admin_notices', plugins_url() . '/woocommerce-abandoned-cart/assets/js/admin/wcal_ts_dismiss_notice.js' );
1915
- wp_localize_script( 'wcal_admin_notices', 'wcal_dismiss_params', array(
1916
- 'ajax_url' => admin_url( 'admin-ajax.php' )
 
 
 
 
 
 
 
 
 
1917
  )
1918
  );
1919
  }
@@ -1921,12 +2179,13 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1921
 
1922
  /**
1923
  * It will add the parameter to the editor.
 
1924
  * @hook tiny_mce_before_init
1925
- * @param array $in
1926
- * @return array $in
1927
  * @since 2.6
1928
  */
1929
- function wcal_format_tiny_MCE( $in ) {
1930
  $in['force_root_block'] = false;
1931
  $in['valid_children'] = '+body[style]';
1932
  $in['remove_linebreaks'] = false;
@@ -1943,63 +2202,65 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
1943
  $in['wpautop'] = false;
1944
  $in['apply_source_formatting'] = true;
1945
  $in['cleanup'] = true;
1946
- $in['convert_newlines_to_brs'] = FALSE;
1947
  $in['fullpage_default_xml_pi'] = false;
1948
  $in['convert_urls'] = false;
1949
- // Do not remove redundant BR tags
1950
- $in['remove_redundant_brs'] = false;
1951
  return $in;
1952
  }
1953
 
1954
  /**
1955
  * It will add the necesaary css for the plugin.
 
1956
  * @hook admin_enqueue_scripts
1957
- * @param string $hook Name of page
1958
  * @since 1.0
1959
  */
1960
- function wcal_enqueue_scripts_css( $hook ) {
1961
 
1962
  global $pagenow;
1963
 
1964
- $page = isset( $_GET['page'] ) ? $_GET['page'] : '';
 
1965
 
1966
- if ( $page != 'woocommerce_ac_page' ) {
1967
  return;
1968
- } else if ( $page === 'woocommerce_ac_page' && ( isset( $_GET['action'] ) && 'dashboard' === $_GET[ 'action' ] ) || ! isset( $_GET[ 'action' ] ) ) {
1969
- wp_enqueue_style( 'wcal-dashboard-adv', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/wcal_reports_adv.css' );
1970
 
1971
- wp_register_style( 'bootstrap_css', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/bootstrap.min.css', '', '', 'all' );
1972
  wp_enqueue_style( 'bootstrap_css' );
1973
 
1974
- wp_enqueue_style( 'wcal-font-awesome', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/font-awesome.css' );
1975
-
1976
- wp_enqueue_style( 'wcal-font-awesome-min', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/font-awesome.min.css' );
 
 
 
 
 
1977
 
1978
- wp_enqueue_style( 'jquery-ui', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/jquery-ui.css', '', '', false );
1979
- wp_enqueue_style( 'woocommerce_admin_styles', plugins_url() . '/woocommerce/assets/css/admin.css' );
1980
- wp_enqueue_style( 'jquery-ui-style', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/jquery-ui-smoothness.css' );
1981
- wp_enqueue_style( 'wcal-reports', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/wcal_reports.min.css' );
1982
-
1983
- } elseif ( $page === 'woocommerce_ac_page' ) {
1984
 
1985
- wp_enqueue_style( 'jquery-ui', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/jquery-ui.css', '', '', false );
1986
- wp_enqueue_style( 'woocommerce_admin_styles', plugins_url() . '/woocommerce/assets/css/admin.css' );
1987
 
1988
- wp_enqueue_style( 'jquery-ui-style', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/jquery-ui-smoothness.css' );
1989
- wp_enqueue_style( 'abandoned-orders-list', plugins_url() . '/woocommerce-abandoned-cart/assets/css/view.abandoned.orders.style.css' );
1990
- wp_enqueue_style( 'wcal_email_template', plugins_url() . '/woocommerce-abandoned-cart/assets/css/wcal_template_activate.css' );
1991
- wp_enqueue_style( 'wcal_cart_details', plugins_url() . '/woocommerce-abandoned-cart/assets/css/admin/wcal_abandoned_cart_detail_modal.min.css' );
1992
  }
1993
  }
1994
 
1995
-
1996
  /**
1997
  * When we have added the wp list table for the listing then while deleting the record with the bulk action it was showing
1998
  * the notice. To overcome the wp redirect warning we need to start the ob_start.
 
1999
  * @hook init
2000
  * @since 2.5.2
2001
  */
2002
- function wcal_app_output_buffer() {
2003
  ob_start();
2004
  }
2005
 
@@ -2008,26 +2269,27 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
2008
  * It will also update the template records and display the template fields.
2009
  * It will also show the abandoned cart details page.
2010
  * It will also show the details of all the tabs.
 
2011
  * @globals mixed $wpdb
2012
  * @since 1.0
2013
  */
2014
- function wcal_menu_page() {
2015
 
2016
  if ( is_user_logged_in() ) {
2017
  global $wpdb;
2018
- // Check the user capabilities
2019
  if ( ! current_user_can( 'manage_woocommerce' ) ) {
2020
- wp_die( __( 'You do not have sufficient permissions to access this page.', 'woocommerce-abandoned-cart' ) );
2021
  }
2022
  ?>
2023
  <div class="wrap">
2024
- <h2><?php _e( 'WooCommerce - Abandon Cart Lite', 'woocommerce-abandoned-cart' ); ?></h2>
2025
  <?php
2026
 
2027
- if ( isset( $_GET['ac_update'] ) && 'email_templates' === $_GET['ac_update'] ) {
2028
  $status = wcal_common::update_templates_table();
2029
 
2030
- if ( $status !== false ) {
2031
  wcal_common::show_update_success();
2032
  } else {
2033
  wcal_common::show_update_failure();
@@ -2035,28 +2297,19 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
2035
  }
2036
 
2037
  if ( isset( $_GET['action'] ) ) {
2038
- $action = $_GET['action'];
2039
  } else {
2040
- $action = "";
2041
  $action = apply_filters( 'wcal_default_tab', $action );
2042
  }
2043
- if ( isset( $_GET['mode'] ) ) {
2044
- $mode = $_GET['mode'];
2045
- } else {
2046
- $mode = "";
2047
- }
2048
  $this->wcal_display_tabs();
2049
 
2050
- do_action ( 'wcal_add_tab_content' );
 
 
 
2051
 
2052
- /**
2053
- * When we delete the item from the below drop down it is registred in action 2
2054
- */
2055
- if ( isset( $_GET['action2'] ) ) {
2056
- $action_two = $_GET['action2'];
2057
- } else {
2058
- $action_two = "";
2059
- }
2060
  // Detect when a bulk action is being triggered on abandoned orders page.
2061
  if ( 'wcal_delete' === $action || 'wcal_delete' === $action_two ) {
2062
  $ids = isset( $_GET['abandoned_order_id'] ) && is_array( $_GET['abandoned_order_id'] ) ? array_map( 'intval', wp_unslash( $_GET['abandoned_order_id'] ) ) : sanitize_text_field( wp_unslash( $_GET['abandoned_order_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
@@ -2091,7 +2344,7 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
2091
 
2092
  // Detect when a bulk action is being triggered on templates page.
2093
  if ( 'wcal_delete_template' === $action || 'wcal_delete_template' === $action_two ) {
2094
- $ids = isset( $_GET['template_id'] ) ? sanitize_text_field( wp_unslash( $_GET['template_id'] ) ) : false;
2095
  if ( ! is_array( $ids ) ) {
2096
  $ids = array( $ids );
2097
  }
@@ -2123,102 +2376,98 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
2123
  <div id="message" class="updated fade">
2124
  <p><strong><?php esc_html_e( 'The Template has been successfully deleted.', 'woocommerce-abandoned-cart' ); ?></strong></p>
2125
  </div>
2126
- <?php }
2127
- if ( 'emailsettings' == $action ) {
2128
- // Save the field values
 
2129
  ?>
2130
- <p><?php _e( 'Change settings for sending email notifications to Customers, to Admin etc.', 'woocommerce-abandoned-cart' ); ?></p>
2131
  <div id="content">
2132
  <?php
2133
- $wcal_general_settings_class = $wcal_email_setting = $wcap_sms_settings = $wcap_atc_settings = $wcap_fb_settings = "";
2134
-
2135
- $section = isset( $_GET[ 'wcal_section' ] ) ? $_GET[ 'wcal_section' ] : '';
2136
-
2137
- switch( $section ) {
2138
-
2139
- case 'wcal_general_settings':
2140
- case '':
2141
- $wcal_general_settings_class = "current";
2142
- break;
2143
-
2144
- case 'wcal_email_settings':
2145
- $wcal_email_setting = "current";
2146
- break;
2147
-
2148
- case 'wcap_sms_settings':
2149
- $wcap_sms_settings = "current";
2150
- break;
2151
-
2152
- case 'wcap_atc_settings':
2153
- $wcap_atc_settings = "current";
2154
- break;
2155
-
2156
- case 'wcap_fb_settings':
2157
- $wcap_fb_settings = "current";
2158
- break;
2159
-
2160
- default:
2161
- $wcal_general_settings_class = "current";
2162
- break;
2163
-
2164
- }
2165
- ?>
2166
  <ul class="subsubsub" id="wcal_general_settings_list">
2167
  <li>
2168
- <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcal_general_settings" class="<?php echo $wcal_general_settings_class; ?>"><?php _e( 'General Settings', 'woocommerce-abandoned-cart' );?> </a> |
2169
  </li>
2170
- <li>
2171
- <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcal_email_settings" class="<?php echo $wcal_email_setting; ?>"><?php _e( 'Email Sending Settings', 'woocommerce-abandoned-cart' );?> </a> |
2172
  </li>
2173
  <li>
2174
- <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_atc_settings" class="<?php echo $wcap_atc_settings; ?>"><?php _e( 'Add To Cart Popup Editor', 'woocommerce-ac' );?> </a> |
2175
  </li>
2176
  <li>
2177
- <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_fb_settings" class="<?php echo $wcap_fb_settings; ?>"><?php _e( 'Facebook Messenger', 'woocommerce-ac' );?> </a> |
2178
  </li>
2179
  <li>
2180
- <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_sms_settings" class="<?php echo $wcap_sms_settings; ?>"><?php _e( 'SMS', 'woocommerce-ac' );?> </a>
2181
  </li>
2182
-
2183
  </ul>
2184
  <br class="clear">
2185
- <?php
2186
- if ( 'wcal_general_settings' == $section || '' == $section ) {
2187
- ?>
2188
  <form method="post" action="options.php">
2189
  <?php settings_fields( 'woocommerce_ac_settings' ); ?>
2190
  <?php do_settings_sections( 'woocommerce_ac_page' ); ?>
2191
  <?php settings_errors(); ?>
2192
  <?php submit_button(); ?>
2193
  </form>
2194
- <?php
2195
- } else if ( 'wcal_email_settings' == $section ) {
2196
- ?>
2197
  <form method="post" action="options.php">
2198
- <?php settings_fields ( 'woocommerce_ac_email_settings' ); ?>
2199
  <?php do_settings_sections( 'woocommerce_ac_email_page' ); ?>
2200
  <?php settings_errors(); ?>
2201
  <?php submit_button(); ?>
2202
  </form>
2203
- <?php
2204
- } elseif( 'wcap_atc_settings' == $section ) {
2205
  WCAP_Pro_Settings::wcap_atc_settings();
2206
- } elseif( 'wcap_fb_settings' == $section ) {
2207
  WCAP_Pro_Settings::wcap_fb_settings();
2208
- } elseif( 'wcap_sms_settings' == $section ) {
2209
  WCAP_Pro_Settings::wcap_sms_settings();
2210
  }
2211
  ?>
2212
  </div>
2213
- <?php
2214
- } else if ( 'dashboard' === $action || '' === $action || '-1' === $action || '1' === $action_two ) {
2215
- include_once( 'includes/classes/class-wcal-dashboard-report.php' );
2216
- Wcal_Dashboard_Report::wcal_dashboard_display();
2217
 
2218
- } else if ( $action == 'listcart' ) {
2219
-
2220
- ?>
2221
- <p> <?php _e( 'The list below shows all Abandoned Carts which have remained in cart for a time higher than the "Cart abandoned cut-off time" setting.', 'woocommerce-abandoned-cart' );?> </p>
2222
  <?php
2223
  $get_all_abandoned_count = wcal_common::wcal_get_abandoned_order_count( 'wcal_all_abandoned' );
2224
  $get_registered_user_ac_count = wcal_common::wcal_get_abandoned_order_count( 'wcal_all_registered' );
@@ -2233,650 +2482,704 @@ if ( ! class_exists( 'woocommerce_abandon_cart_lite' ) ) {
2233
  if ( $get_guest_user_ac_count > 1 ) {
2234
  $wcal_user_gus_text = 'Users';
2235
  }
2236
- $wcal_all_abandoned_carts = $section = $wcal_all_registered = $wcal_all_guest = $wcal_all_visitor = "" ;
2237
-
2238
- if ( isset( $_GET[ 'wcal_section' ] ) ) {
2239
- $section = $_GET[ 'wcal_section' ];
2240
- } else {
2241
- $section = '';
2242
- }
2243
- if ( 'wcal_all_abandoned' == $section || '' == $section ) {
2244
- $wcal_all_abandoned_carts = "current";
2245
  }
2246
 
2247
- if ( 'wcal_all_registered' == $section ) {
2248
- $wcal_all_registered = "current";
2249
- $wcal_all_abandoned_carts = "";
2250
  }
2251
- if ( 'wcal_all_guest' == $section ) {
2252
- $wcal_all_guest = "current";
2253
- $wcal_all_abandoned_carts = "";
2254
  }
2255
 
2256
- if ( 'wcal_all_visitor' == $section ) {
2257
- $wcal_all_visitor = "current";
2258
- $wcal_all_abandoned_carts = "";
2259
  }
2260
  ?>
2261
  <ul class="subsubsub" id="wcal_recovered_orders_list">
2262
  <li>
2263
- <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_abandoned" class="<?php echo $wcal_all_abandoned_carts; ?>"><?php _e( "All ", 'woocommerce-abandoned-cart' ) ;?> <span class = "count" > <?php echo "( $get_all_abandoned_count )" ?> </span></a>
2264
  </li>
2265
 
2266
- <?php if ( $get_registered_user_ac_count > 0 ) { ?>
2267
- <li>
2268
- | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_registered" class="<?php echo $wcal_all_registered; ?>"><?php printf( __( 'Registered %s', 'woocommerce-abandoned-cart' ), $wcal_user_reg_text ); ?> <span class = "count" > <?php echo "( $get_registered_user_ac_count )" ?> </span></a>
2269
  </li>
2270
  <?php } ?>
2271
 
2272
- <?php if ( $get_guest_user_ac_count > 0 ) { ?>
2273
- <li>
2274
- | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_guest" class="<?php echo $wcal_all_guest; ?>"><?php printf( __( 'Guest %s', 'woocommerce-abandoned-cart' ), $wcal_user_gus_text ); ?> <span class = "count" > <?php echo "( $get_guest_user_ac_count )" ?> </span></a>
2275
  </li>
2276
  <?php } ?>
2277
 
2278
- <?php if ( $get_visitor_user_ac_count > 0 ) { ?>
2279
  <li>
2280
- | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_visitor" class="<?php echo $wcal_all_visitor; ?>"><?php _e( "Carts without Customer Details", 'woocommerce-abandoned-cart' ); ?> <span class = "count" > <?php echo "( $get_visitor_user_ac_count )" ?> </span></a>
2281
  </li>
2282
  <?php } ?>
2283
  </ul>
2284
 
2285
  <?php
2286
  global $wpdb;
2287
- include_once( 'includes/classes/class-wcal-abandoned-orders-table.php' );
2288
  $wcal_abandoned_order_list = new WCAL_Abandoned_Orders_Table();
2289
  $wcal_abandoned_order_list->wcal_abandoned_order_prepare_items();
2290
  ?>
2291
  <div class="wrap">
2292
  <form id="wcal-abandoned-orders" method="get" >
2293
  <input type="hidden" name="page" value="woocommerce_ac_page" />
2294
- <input type="hidden" name="action" value="listcart" />
2295
- <?php $wcal_abandoned_order_list->display(); ?>
2296
  </form>
2297
  </div>
2298
  <?php
2299
- } elseif ( ( 'emailtemplates' == $action && ( 'edittemplate' != $mode && 'addnewtemplate' != $mode ) || '' == $action || '-1' == $action || '-1' == $action_two ) ) {
2300
- ?>
2301
- <p> <?php _e( 'Add email templates at different intervals to maximize the possibility of recovering your abandoned carts.', 'woocommerce-abandoned-cart' );?> </p>
2302
- <?php
2303
- // Save the field values
2304
- $insert_template_successfuly = $update_template_successfuly = '';
2305
- if ( isset( $_POST['ac_settings_frm'] ) && 'save' == $_POST['ac_settings_frm'] ) {
2306
- $woocommerce_ac_email_subject = trim( htmlspecialchars( $_POST['woocommerce_ac_email_subject'] ), ENT_QUOTES );
2307
- $woocommerce_ac_email_body = trim( $_POST['woocommerce_ac_email_body'] );
2308
- $woocommerce_ac_template_name = trim( $_POST['woocommerce_ac_template_name'] );
2309
- $woocommerce_ac_email_header = stripslashes( trim( htmlspecialchars( $_POST['wcal_wc_email_header'] ), ENT_QUOTES ) );
2310
-
2311
- $email_frequency = trim( $_POST['email_frequency'] );
2312
- $day_or_hour = trim( $_POST['day_or_hour'] );
2313
- $is_wc_template = ( empty( $_POST['is_wc_template'] ) ) ? '0' : '1';
2314
- $default_value = 0 ;
2315
-
2316
- $query = "INSERT INTO `".$wpdb->prefix."ac_email_templates_lite`
2317
- (subject, body, frequency, day_or_hour, template_name, is_wc_template, default_template, wc_email_header )
2318
- VALUES ( %s, %s, %d, %s, %s, %s, %d, %s )";
2319
-
2320
- $insert_template_successfuly = $wpdb->query( $wpdb->prepare( $query,
2321
- $woocommerce_ac_email_subject,
2322
- $woocommerce_ac_email_body,
2323
- $email_frequency,
2324
- $day_or_hour,
2325
- $woocommerce_ac_template_name,
2326
- $is_wc_template,
2327
- $default_value,
2328
- $woocommerce_ac_email_header )
2329
- );
2330
- }
2331
-
2332
- if ( isset( $_POST['ac_settings_frm'] ) && 'update' == $_POST['ac_settings_frm'] ) {
2333
-
2334
- $updated_is_active = '0';
2335
 
2336
- $email_frequency = trim( $_POST['email_frequency'] );
2337
- $day_or_hour = trim( $_POST['day_or_hour'] );
2338
- $is_wc_template = ( empty( $_POST['is_wc_template'] ) ) ? '0' : '1';
2339
 
2340
- $woocommerce_ac_email_subject = trim( htmlspecialchars( $_POST['woocommerce_ac_email_subject'] ), ENT_QUOTES );
2341
- $woocommerce_ac_email_body = trim( $_POST['woocommerce_ac_email_body'] );
2342
- $woocommerce_ac_template_name = trim( $_POST['woocommerce_ac_template_name'] );
2343
- $woocommerce_ac_email_header = stripslashes( trim( htmlspecialchars( $_POST['wcal_wc_email_header'] ), ENT_QUOTES ) );
2344
- $id = trim( $_POST['id'] );
2345
 
2346
- $check_query = "SELECT * FROM `".$wpdb->prefix."ac_email_templates_lite`
2347
- WHERE id = %d ";
2348
- $check_results = $wpdb->get_results( $wpdb->prepare( $check_query, $id ) );
2349
- $default_value = '';
 
 
 
2350
 
2351
- if ( count( $check_results ) > 0 ) {
2352
- if ( isset( $check_results[0]->default_template ) && $check_results[0]->default_template == '1' ) {
2353
- $default_value = '1';
2354
- }
2355
  }
2356
-
2357
- $query_update_latest = "UPDATE `".$wpdb->prefix."ac_email_templates_lite`
2358
- SET
2359
- subject = %s,
2360
- body = %s,
2361
- frequency = %d,
2362
- day_or_hour = %s,
2363
- template_name = %s,
2364
- is_wc_template = %s,
2365
- default_template = %d,
2366
- wc_email_header = %s
2367
- WHERE id = %d ";
2368
-
2369
- $update_template_successfuly = $wpdb->query( $wpdb->prepare( $query_update_latest,
2370
- $woocommerce_ac_email_subject,
2371
- $woocommerce_ac_email_body,
2372
- $email_frequency,
2373
- $day_or_hour,
2374
- $woocommerce_ac_template_name,
2375
- $is_wc_template,
2376
- $default_value,
2377
- $woocommerce_ac_email_header,
2378
- $id )
2379
- );
2380
-
2381
- }
2382
-
2383
- if ( 'emailtemplates' == $action && 'removetemplate' == $mode ) {
2384
- $id_remove = $_GET['id'];
2385
- $query_remove = "DELETE FROM `".$wpdb->prefix."ac_email_templates_lite` WHERE id= %d ";
2386
- $wpdb->query( $wpdb->prepare( $query_remove, $id_remove ) );
2387
  }
2388
 
2389
- if ( 'emailtemplates' == $action && 'activate_template' == $mode ) {
2390
- $template_id = $_GET['id'];
2391
- $current_template_status = $_GET['active_state'];
2392
-
2393
- if ( "1" == $current_template_status ) {
2394
- $active = "0";
2395
- } else {
2396
- $active = "1";
2397
-
2398
- $query_update = "SELECT * FROM `".$wpdb->prefix."ac_email_templates_lite` WHERE id ='" . $template_id . "'";
2399
- $get_selected_template_result = $wpdb->get_results( $query_update );
 
 
 
 
2400
 
2401
- $email_frequncy = $get_selected_template_result[0]->frequency;
2402
- $email_day_or_hour = $get_selected_template_result[0]->day_or_hour;
 
 
 
 
 
 
 
2403
 
2404
- $query_update = "UPDATE `".$wpdb->prefix."ac_email_templates_lite` SET is_active='0' WHERE frequency='" . $email_frequncy . "' AND day_or_hour='" . $email_day_or_hour . "' ";
2405
- $wcap_updated = $wpdb->query( $query_update );
2406
- }
2407
 
2408
- $query_update = "UPDATE `" . $wpdb->prefix . "ac_email_templates_lite`
2409
- SET
2410
- is_active = '" . $active . "'
2411
- WHERE id = '" . $template_id . "' ";
2412
- $wpdb->query( $query_update );
 
 
 
 
 
2413
 
2414
- wp_safe_redirect( admin_url( '/admin.php?page=woocommerce_ac_page&action=emailtemplates' ) );
 
 
 
 
 
 
 
 
 
2415
  }
2416
 
2417
- if ( isset( $_POST['ac_settings_frm'] ) && 'save' == $_POST['ac_settings_frm'] && ( isset( $insert_template_successfuly ) && $insert_template_successfuly != '' ) ) { ?>
2418
- <div id="message" class="updated fade">
2419
- <p>
2420
- <strong>
2421
- <?php _e( 'The Email Template has been successfully added. In order to start sending this email to your customers, please activate it.', 'woocommerce-abandoned-cart' ); ?>
2422
- </strong>
2423
- </p>
2424
- </div>
2425
- <?php } else if ( isset( $_POST['ac_settings_frm'] ) && 'save' == $_POST['ac_settings_frm'] && ( isset( $insert_template_successfuly ) && '' == $insert_template_successfuly ) ) {
2426
- ?>
2427
- <div id="message" class="error fade">
2428
- <p>
2429
- <strong>
2430
- <?php _e( 'There was a problem adding the email template. Please contact the plugin author via <a href= "https://wordpress.org/support/plugin/woocommerce-abandoned-cart">support forum</a>.', 'woocommerce-abandoned-cart' ); ?>
2431
- </strong>
2432
- </p>
2433
- </div>
2434
- <?php
2435
- }
2436
 
2437
- if ( isset( $_POST['ac_settings_frm'] ) && 'update' == $_POST['ac_settings_frm'] && isset( $update_template_successfuly ) && $update_template_successfuly !== false ) { ?>
2438
- <div id="message" class="updated fade">
2439
- <p>
2440
- <strong>
2441
- <?php _e( 'The Email Template has been successfully updated.', 'woocommerce-abandoned-cart' ); ?>
2442
- </strong>
2443
- </p>
2444
- </div>
2445
- <?php } else if ( isset( $_POST['ac_settings_frm'] ) && $_POST['ac_settings_frm'] == 'update' && isset( $update_template_successfuly) && $update_template_successfuly === false ){
2446
- ?>
2447
- <div id="message" class="error fade">
2448
- <p>
2449
- <strong>
2450
- <?php _e( 'There was a problem updating the email template. Please contact the plugin author via <a href= "https://wordpress.org/support/plugin/woocommerce-abandoned-cart">support forum</a>.', 'woocommerce-abandoned-cart' ); ?>
2451
- </strong>
2452
- </p>
2453
- </div>
2454
- <?php
2455
- }
2456
  ?>
2457
- <div class="tablenav">
2458
- <p style="float:left;">
2459
- <a cursor: pointer; href="<?php echo "admin.php?page=woocommerce_ac_page&action=emailtemplates&mode=addnewtemplate"; ?>" class="button-secondary"><?php _e( 'Add New Template', 'woocommerce-abandoned-cart' ); ?>
2460
- </a>
 
2461
  </p>
 
 
 
2462
 
2463
- <?php
2464
- /* From here you can do whatever you want with the data from the $result link. */
2465
- include_once('includes/classes/class-wcal-templates-table.php');
2466
- $wcal_template_list = new WCAL_Templates_Table();
2467
- $wcal_template_list->wcal_templates_prepare_items();
2468
- ?>
2469
- <div class="wrap">
2470
- <form id="wcal-abandoned-templates" method="get" >
2471
- <input type="hidden" name="page" value="woocommerce_ac_page" />
2472
- <input type="hidden" name="action" value="emailtemplates" />
2473
- <?php $wcal_template_list->display(); ?>
2474
- </form>
2475
- </div>
2476
  </div>
2477
  <?php
2478
- } elseif ( 'stats' == $action || '' == $action ) {
2479
  ?>
2480
- <p>
2481
- <script language='javascript'>
2482
- jQuery( document ).ready( function() {
2483
- jQuery( '#duration_select' ).change( function() {
2484
- var group_name = jQuery( '#duration_select' ).val();
2485
- var today = new Date();
2486
- var start_date = "";
2487
- var end_date = "";
2488
- if ( group_name == "yesterday" ) {
2489
- start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 1 );
2490
- end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 1 );
2491
- } else if ( group_name == "today") {
2492
- start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2493
- end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2494
- } else if ( group_name == "last_seven" ) {
2495
- start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 7 );
2496
- end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2497
- } else if ( group_name == "last_fifteen" ) {
2498
- start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 15 );
2499
- end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2500
- } else if ( group_name == "last_thirty" ) {
2501
- start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 30 );
2502
- end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2503
- } else if ( group_name == "last_ninety" ) {
2504
- start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 90 );
2505
- end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2506
- } else if ( group_name == "last_year_days" ) {
2507
- start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 365 );
2508
- end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2509
- }
2510
 
2511
- var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
2512
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2513
 
2514
- var start_date_value = start_date.getDate() + " " + monthNames[start_date.getMonth()] + " " + start_date.getFullYear();
2515
- var end_date_value = end_date.getDate() + " " + monthNames[end_date.getMonth()] + " " + end_date.getFullYear();
2516
 
2517
- jQuery( '#start_date' ).val( start_date_value );
2518
- jQuery( '#end_date' ).val( end_date_value );
2519
- } );
2520
- });
2521
- </script>
2522
- <?php
2523
 
2524
- if ( isset( $_POST['duration_select'] ) ){
2525
- $duration_range = $_POST['duration_select'];
2526
- } else {
2527
- $duration_range = "";
2528
- }
2529
- if ( '' == $duration_range ) {
2530
- if ( isset( $_GET['duration_select'] ) ){
2531
- $duration_range = $_GET['duration_select'];
2532
- }
 
2533
  }
2534
- if ( '' == $duration_range ) $duration_range = "last_seven";
 
 
 
2535
 
2536
- _e( 'The Report below shows how many Abandoned Carts we were able to recover for you by sending automatic emails to encourage shoppers.', 'woocommerce-abandoned-cart');
2537
- ?>
2538
- <div id="recovered_stats" class="postbox" style="display:block">
2539
- <div class="inside">
2540
- <form method="post" action="admin.php?page=woocommerce_ac_page&action=stats" id="ac_stats">
2541
- <select id="duration_select" name="duration_select" >
2542
- <?php
2543
- foreach ( $this->duration_range_select as $key => $value ) {
2544
- $sel = "";
2545
- if ( $key == $duration_range ) {
2546
- $sel = " selected ";
2547
- }
2548
- echo"<option value='$key' $sel> $value </option>";
2549
- }
2550
- $date_sett = $this->start_end_dates[ $duration_range ];
2551
- ?>
2552
- </select>
2553
- <script type="text/javascript">
2554
- jQuery( document ).ready( function()
2555
- {
2556
- var formats = ["d.m.y", "d M yy","MM d, yy"];
2557
- jQuery( "#start_date" ).datepicker( { dateFormat: formats[1] } );
2558
- });
2559
-
2560
- jQuery( document ).ready( function()
2561
- {
2562
- var formats = ["d.m.y", "d M yy","MM d, yy"];
2563
- jQuery( "#end_date" ).datepicker( { dateFormat: formats[1] } );
2564
- });
2565
- </script>
2566
  <?php
2567
- include_once('includes/classes/class-wcal-recover-orders-table.php');
2568
- $wcal_recover_orders_list = new WCAL_Recover_Orders_Table();
2569
- $wcal_recover_orders_list->wcal_recovered_orders_prepare_items();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2570
 
2571
- if ( isset( $_POST['start_date'] ) ) $start_date_range = $_POST['start_date'];
2572
- else $start_date_range = "";
2573
 
2574
- if ( $start_date_range == "" ) {
2575
- $start_date_range = $date_sett['start_date'];
2576
- }
2577
 
2578
- if ( isset( $_POST['end_date'] ) ) $end_date_range = $_POST['end_date'];
2579
- else $end_date_range = "";
2580
 
2581
- if ( $end_date_range == "" ) {
2582
- $end_date_range = $date_sett['end_date'];
2583
- }
2584
- ?>
2585
- <label class="start_label" for="start_day"> <?php _e( 'Start Date:', 'woocommerce-abandoned-cart' ); ?> </label>
2586
- <input type="text" id="start_date" name="start_date" readonly="readonly" value="<?php echo $start_date_range; ?>"/>
2587
- <label class="end_label" for="end_day"> <?php _e( 'End Date:', 'woocommerce-abandoned-cart' ); ?> </label>
2588
- <input type="text" id="end_date" name="end_date" readonly="readonly" value="<?php echo $end_date_range; ?>"/>
2589
- <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Go', 'woocommerce-abandoned-cart' ); ?>" />
2590
- </form>
2591
- </div>
1
  <?php
2
+ /**
3
+ * Plugin Name: Abandoned Cart Lite for WooCommerce
4
+ * Plugin URI: http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro
5
+ * Description: This plugin captures abandoned carts by logged-in users & emails them about it. <strong><a href="http://www.tychesoftwares.com/store/premium-plugins/woocommerce-abandoned-cart-pro">Click here to get the PRO Version.</a></strong>
6
+ * Version: 5.8.2
7
+ * Author: Tyche Softwares
8
+ * Author URI: http://www.tychesoftwares.com/
9
+ * Text Domain: woocommerce-abandoned-cart
10
+ * Domain Path: /i18n/languages/
11
+ * Requires PHP: 5.6
12
+ * WC requires at least: 3.0.0
13
+ * WC tested up to: 4.6.1
14
+ *
15
+ * @package Abandoned-Cart-Lite-for-WooCommerce
16
+ */
17
+
18
+ require_once 'class-wcal-update.php';
19
+ require_once 'includes/wcal_class-guest.php';
20
+ require_once 'includes/class-wcal-default-template-settings.php';
21
+ require_once 'includes/class-wcal-delete-handler.php';
22
+ require_once 'includes/classes/class-wcal-aes.php';
23
+ require_once 'includes/classes/class-wcal-aes-counter.php';
24
+ require_once 'includes/wcal-common.php';
25
+
26
+ require_once 'includes/class-wcal-admin-notice.php';
27
+ require_once 'includes/wcal_data_tracking_message.php';
28
+ require_once 'includes/admin/class-wcal-personal-data-eraser.php';
29
+ require_once 'includes/admin/class-wcal-privacy-export.php';
30
+ require_once 'includes/admin/class-wcal-abandoned-cart-details.php';
31
+
32
+ require_once 'includes/admin/wcap_pro_settings.php';
33
+ require_once 'includes/admin/wcap_pro_settings_callbacks.php';
34
+ require_once 'includes/admin/wcap_add_cart_popup_modal.php';
 
 
35
 
36
  load_plugin_textdomain( 'woocommerce-abandoned-cart', false, basename( dirname( __FILE__ ) ) . '/i18n/languages' );
37
 
59
  * @package Abandoned-Cart-Lite-for-WooCommerce/Core
60
  */
61
  class woocommerce_abandon_cart_lite {
62
+ /**
63
+ * Duration One hour.
64
+ *
65
+ * @var int
66
+ */
67
+ public $one_hour;
68
+ /**
69
+ * Duration three hours.
70
+ *
71
+ * @var int
72
+ */
73
+ public $three_hours;
74
+ /**
75
+ * Duration six hours.
76
+ *
77
+ * @var int
78
+ */
79
+ public $six_hours;
80
+ /**
81
+ * Duration 12 hours.
82
+ *
83
+ * @var int
84
+ */
85
+ public $twelve_hours;
86
+ /**
87
+ * Duration One day.
88
+ *
89
+ * @var int
90
+ */
91
+ public $one_day;
92
+ /**
93
+ * Duration One week.
94
+ *
95
+ * @var int
96
+ */
97
+ public $one_week;
98
+ /**
99
+ * Duration range select
100
+ *
101
+ * @var array
102
+ */
103
+ public $duration_range_select;
104
+ /**
105
+ * Duration start & end dates
106
+ *
107
+ * @var array
108
+ */
109
+ public $start_end_dates;
110
  /**
111
  * The constructor will add the hooks, filters and the variable which will be used all over the plugin.
112
  *
113
  * @since 1.0
114
  */
115
  public function __construct() {
116
+ if ( ! defined( 'WCAL_PLUGIN_URL' ) ) {
117
  define( 'WCAL_PLUGIN_URL', untrailingslashit( plugins_url( '/', __FILE__ ) ) );
118
  }
119
 
120
  if ( ! defined( 'WCAL_PLUGIN_VERSION' ) ) {
121
+ define( 'WCAL_PLUGIN_VERSION', '5.8.2' );
122
  }
123
+ $this->one_hour = 60 * 60;
124
+ $this->three_hours = 3 * $this->one_hour;
125
+ $this->six_hours = 6 * $this->one_hour;
126
+ $this->twelve_hours = 12 * $this->one_hour;
127
+ $this->one_day = 24 * $this->one_hour;
128
+ $this->one_week = 7 * $this->one_day;
129
  $this->duration_range_select = array(
130
  'yesterday' => 'Yesterday',
131
  'today' => 'Today',
133
  'last_fifteen' => 'Last 15 days',
134
  'last_thirty' => 'Last 30 days',
135
  'last_ninety' => 'Last 90 days',
136
+ 'last_year_days' => 'Last 365',
137
  );
138
 
139
  $this->start_end_dates = array(
140
  'yesterday' => array(
141
+ 'start_date' => date( 'd M Y', ( current_time( 'timestamp' ) - 24 * 60 * 60 ) ), // phpcs:ignore
142
+ 'end_date' => date( 'd M Y', ( current_time( 'timestamp' ) - 7 * 24 * 60 * 60 ) ), // phpcs:ignore
143
  ),
144
  'today' => array(
145
+ 'start_date' => date( 'd M Y', ( current_time( 'timestamp' ) ) ), // phpcs:ignore
146
+ 'end_date' => date( 'd M Y', ( current_time( 'timestamp' ) ) ), // phpcs:ignore
147
  ),
148
  'last_seven' => array(
149
+ 'start_date' => date( 'd M Y', ( current_time( 'timestamp' ) - 7 * 24 * 60 * 60 ) ), // phpcs:ignore
150
+ 'end_date' => date( 'd M Y', ( current_time( 'timestamp' ) ) ), // phpcs:ignore
151
  ),
152
  'last_fifteen' => array(
153
+ 'start_date' => date( 'd M Y', ( current_time( 'timestamp' ) - 15 * 24 * 60 * 60 ) ), // phpcs:ignore
154
+ 'end_date' => date( 'd M Y', ( current_time( 'timestamp' ) ) ), // phpcs:ignore
155
  ),
156
  'last_thirty' => array(
157
+ 'start_date' => date( 'd M Y', ( current_time( 'timestamp' ) - 30 * 24 * 60 * 60 ) ), // phpcs:ignore
158
+ 'end_date' => date( 'd M Y', ( current_time( 'timestamp' ) ) ), // phpcs:ignore
159
  ),
160
  'last_ninety' => array(
161
+ 'start_date' => date( 'd M Y', ( current_time( 'timestamp' ) - 90 * 24 * 60 * 60 ) ), // phpcs:ignore
162
+ 'end_date' => date( 'd M Y', ( current_time( 'timestamp' ) ) ), // phpcs:ignore
163
  ),
164
  'last_year_days' => array(
165
+ 'start_date' => date( 'd M Y', ( current_time( 'timestamp' ) - 365 * 24 * 60 * 60 ) ), // phpcs:ignore
166
+ 'end_date' => date( 'd M Y', ( current_time( 'timestamp' ) ) ), // phpcs:ignore
167
  ),
168
  );
169
 
172
  register_deactivation_hook( __FILE__, array( &$this, 'wcal_deactivate' ) );
173
 
174
  // Action Scheduler for Cron.
175
+ require_once 'includes/libraries/action-scheduler/action-scheduler.php';
176
  add_action( 'init', array( &$this, 'wcal_add_scheduled_action' ) );
177
+ require_once 'cron/wcal_send_email.php';
178
+ require_once 'includes/wcal_process_base.php';
179
 
180
  // WordPress Administration Menu.
181
  add_action( 'admin_menu', array( &$this, 'wcal_admin_menu' ) );
192
  add_action( 'admin_init', array( &$this, 'wcal_action_admin_init' ) );
193
 
194
  // Update the options as per settings API.
195
+ add_action( 'admin_init', array( 'Wcal_Update', 'wcal_schedule_update_action' ) );
196
+ add_action( 'wcal_update_db', array( 'Wcal_Update', 'wcal_update_db_check' ) );
197
 
198
+ // WordPress settings API.
199
+ add_action( 'admin_init', array( &$this, 'wcal_initialize_plugin_options' ) );
200
 
201
+ // Language Translation.
202
+ add_action( 'init', array( &$this, 'wcal_update_po_file' ) );
203
 
204
+ add_action( 'init', array( &$this, 'wcal_add_component_file' ) );
205
 
206
+ // track links.
207
+ add_filter( 'template_include', array( &$this, 'wcal_email_track_links' ), 99, 1 );
208
 
209
+ // It will used to unsubcribe the emails.
210
+ add_action( 'template_include', array( &$this, 'wcal_email_unsubscribe' ), 99, 1 );
211
 
212
+ add_action( 'admin_enqueue_scripts', array( &$this, 'wcal_enqueue_scripts_js' ) );
213
+ add_action( 'admin_enqueue_scripts', array( &$this, 'wcal_enqueue_scripts_css' ) );
214
+ // delete abandoned order after X number of days.
215
  if ( class_exists( 'Wcal_Delete_Handler' ) ) {
216
  add_action( 'wcal_clear_carts', array( 'Wcal_Delete_Handler', 'wcal_delete_abandoned_carts_after_x_days' ) );
217
  }
224
  add_action( 'wp_ajax_wcal_abandoned_cart_info', array( &$this, 'wcal_abandoned_cart_info' ) );
225
  add_action( 'wp_ajax_wcal_dismiss_admin_notice', array( &$this, 'wcal_dismiss_admin_notice' ) );
226
 
227
+ add_filter( 'ts_tracker_data', array( 'wcal_common', 'ts_add_plugin_tracking_data' ), 10, 1 );
228
+ add_filter( 'ts_tracker_opt_out_data', array( 'wcal_common', 'ts_get_data_for_opt_out' ), 10, 1 );
229
+ add_filter( 'ts_deativate_plugin_questions', array( &$this, 'wcal_deactivate_add_questions' ), 10, 1 );
230
  }
231
 
232
+ // Plugin Settings link in WP->Plugins page.
233
  $plugin = plugin_basename( __FILE__ );
234
+ add_action( "plugin_action_links_$plugin", array( &$this, 'wcal_settings_link' ) );
235
 
236
+ add_action( 'admin_init', array( $this, 'wcal_preview_emails' ) );
237
+ add_action( 'init', array( $this, 'wcal_app_output_buffer' ) );
238
 
239
+ add_filter( 'admin_footer_text', array( $this, 'wcal_admin_footer_text' ), 1 );
240
 
241
+ add_action( 'admin_notices', array( 'Wcal_Admin_Notice', 'wcal_show_db_update_notice' ) );
242
 
243
  include_once 'includes/frontend/wcal_frontend.php';
244
  }
249
  public static function wcal_add_scheduled_action() {
250
  if ( false === as_next_scheduled_action( 'woocommerce_ac_send_email_action' ) ) {
251
  wp_clear_scheduled_hook( 'woocommerce_ac_send_email_action' ); // Remove the cron job is present.
252
+ as_schedule_recurring_action( time() + 60, 900, 'woocommerce_ac_send_email_action' ); // Schedule recurring action.
253
  }
254
  }
255
+
256
  /**
257
+ * Add Settings link to WP->Plugins page.
258
+ *
259
+ * @param array $links - Links to be displayed.
260
+ * @return array $links - Includes custom links.
261
  * @since 5.3.0
262
  */
263
  public static function wcal_settings_link( $links ) {
269
  /**
270
  * It will load the boilerplate components file. In this file we have included all boilerplate files.
271
  * We need to inlcude this file after the init hook.
272
+ *
273
  * @hook init
274
  */
275
+ public static function wcal_add_component_file() {
276
  if ( is_admin() ) {
277
+ require_once 'includes/wcal_all_component.php';
278
 
279
  }
280
  }
281
  /**
282
  * It will add the Questions while admin deactivate the plugin.
283
+ *
284
+ * @hook ts_deativate_plugin_questions.
285
+ * @param array $wcal_add_questions Blank array.
286
  * @return array $wcal_add_questions List of all questions.
287
  */
288
+ public static function wcal_deactivate_add_questions( $wcal_add_questions ) {
289
 
290
  $wcal_add_questions = array(
291
  0 => array(
292
  'id' => 4,
293
+ 'text' => __( 'Emails are not being sent to customers.', 'woocommerce-abandoned-cart' ),
294
  'input_type' => '',
295
+ 'input_placeholder' => '',
296
+ ),
297
+ 1 => array(
298
  'id' => 5,
299
+ 'text' => __( 'Capturing of cart and other information was not satisfactory.', 'woocommerce-abandoned-cart' ),
300
  'input_type' => '',
301
+ 'input_placeholder' => '',
302
  ),
303
  2 => array(
304
  'id' => 6,
305
+ 'text' => __( 'I cannot see abandoned cart reminder emails records.', 'woocommerce-abandoned-cart' ),
306
  'input_type' => '',
307
+ 'input_placeholder' => '',
308
  ),
309
  3 => array(
310
  'id' => 7,
311
+ 'text' => __( 'I want to upgrade the plugin to the PRO version.', 'woocommerce-abandoned-cart' ),
312
  'input_type' => '',
313
+ 'input_placeholder' => '',
314
+ ),
315
 
316
  );
317
  return $wcal_add_questions;
319
 
320
  /**
321
  * Replace Merge tags in email previews.
322
+ *
323
+ * @param string $content - Email content.
324
+ * @return string $content - content with cart data.
325
  * @since 5.8
326
  */
327
+ public function replace_mergetags( $content ) {
328
+
329
  $admin_args = array(
330
  'role' => 'administrator',
331
  'fields' => array( 'id' ),
332
  );
333
 
334
+ $admin_usr = get_users( $admin_args );
335
+ $uid = $admin_usr[0]->id;
336
+ $admin_phone = get_user_meta( $uid, 'billing_phone', true );
337
 
338
  $wcal_price = wc_price( '150' );
339
  $wcal_total_price = wc_price( '300' );
340
 
341
+ $allowed_html = array(
342
+ 'span' => array(
343
+ 'class' => array(),
344
+ ),
345
+ );
346
+ $spectre_img_src = esc_url( plugins_url( '/assets/images/spectre.jpg', __FILE__ ) );
347
  $replace_data['products_cart'] = "<table border='0' width='100%' cellspacing='0' cellpadding='0'><b>Your Shopping Cart</b>
348
  <tbody>
349
  <tr>
359
 
360
  </tr>
361
  <tr style='background-color:#f4f5f4;'>
362
+ <td><img src = '$spectre_img_src' height='40px' width='40px'></td><td>Spectre</td><td>" . wp_kses( $wcal_price, $allowed_html ) . '</td><td>2</td><td>' . wp_kses( $wcal_total_price, $allowed_html ) . '</td>
363
  </tr>
364
  <tr>
365
  <td>&nbsp;</td>
366
  <td>&nbsp;</td>
367
  <td>&nbsp;</td>
368
  <th>Cart Total:</th>
369
+ <td>' . wp_kses( $wcal_total_price, $allowed_html ) . '</td>
370
  </tr>
371
 
372
  </tbody>
373
+ </table>';
374
+ $replace_data['admin_phone'] = $admin_phone;
375
+ $replace_data['site_title'] = get_bloginfo( 'name' );
376
+ $replace_data['site_url'] = get_option( 'siteurl' );
377
 
 
378
  $content = str_ireplace( '{{products.cart}}', $replace_data['products_cart'], $content );
379
+ $content = str_ireplace( '{{admin.phone}}', $replace_data['admin_phone'], $content );
380
+ $content = str_ireplace( '{{customer.firstname}}', 'John', $content );
381
+ $content = str_ireplace( '{{customer.lastname}}', 'Doe', $content );
382
+ $content = str_ireplace( '{{customer.fullname}}', 'John Doe', $content );
383
  $content = str_ireplace( 'site_title', $replace_data['site_title'], $content );
384
  $content = str_ireplace( 'site_url', $replace_data['site_url'], $content );
385
+
386
  return $content;
387
  }
388
+
389
  /**
390
  * It will ganerate the preview email template.
391
+ *
392
  * @hook admin_init
393
  * @globals mixed $woocommerce
394
  * @since 2.5
395
  */
396
  public function wcal_preview_emails() {
397
  global $woocommerce;
398
+
399
+ if ( isset( $_GET['id'] ) && 0 < sanitize_text_field( wp_unslash( $_GET['id'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
400
  global $wpdb;
401
+ $id = sanitize_text_field( wp_unslash( $_GET['id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
402
+ $content = $wpdb->get_var( // phpcs:ignore
403
+ $wpdb->prepare(
404
+ 'SELECT body FROM `' . $wpdb->prefix . 'ac_email_templates_lite` WHERE id = %d',
405
+ absint( $id )
406
+ )
407
+ );
408
  $content = $this->replace_mergetags( $content );
409
  }
410
 
411
+ if ( isset( $_GET['wcal_preview_woocommerce_mail'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
412
+ if ( isset( $_REQUEST['_wpnonce'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ), 'woocommerce-abandoned-cart' ) ) {
413
  die( 'Security check' );
414
  }
415
  $message = '';
416
+ // create a new email.
417
  if ( $woocommerce->version < '2.3' ) {
418
  global $email_heading;
419
  ob_start();
420
 
421
+ include 'views/wcal-wc-email-template-preview.php';
422
  $mailer = WC()->mailer();
423
  $message = ob_get_clean();
424
  $email_heading = __( 'HTML Email Template', 'woocommerce-abandoned-cart' );
425
+ $message = $mailer->wrap_message( $email_heading, $message );
426
  } else {
427
+ // load the mailer class.
428
+ $mailer = WC()->mailer();
429
+ // get the preview email subject.
430
  $email_heading = __( 'Abandoned cart Email Template', 'woocommerce-abandoned-cart' );
431
+ // get the preview email content.
432
  ob_start();
433
+ if ( isset( $_GET['id'] ) && 0 < sanitize_text_field( wp_unslash( $_GET['id'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
434
  $message = stripslashes( $content );
435
  } else {
436
+ include 'views/wcal-wc-email-template-preview.php';
437
  $message = ob_get_clean();
438
  }
439
+ // create a new email.
440
+ $email = new WC_Email();
441
+ // wrap the content with the email template and then add styles.
442
+ $message = $email->style_inline( $mailer->wrap_message( $email_heading, $message ) );
443
  }
444
+ echo $message; // phpcs:ignore
445
  exit;
446
  }
447
 
448
+ if ( isset( $_GET['wcal_preview_mail'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
449
+ if ( isset( $_REQUEST['_wpnonce'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ), 'woocommerce-abandoned-cart' ) ) {
450
  die( 'Security check' );
451
  }
452
+ // get the preview email content.
453
  ob_start();
454
+ if ( isset( $_GET['id'] ) && 0 < sanitize_text_field( wp_unslash( $_GET['id'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
455
  $message = stripslashes( $content );
456
  } else {
457
+ include_once 'views/wcal-email-template-preview.php';
458
  $message = ob_get_clean();
459
  }
460
+ // print the preview email.
461
+ echo $message; // phpcs:ignore
462
  exit;
463
  }
464
  }
465
 
466
  /**
467
  * In this version we have allowed customer to transalte the plugin string using .po and .pot file.
468
+ *
469
  * @hook init
470
  * @return $loaded
471
  * @since 1.6
472
  */
473
+ public function wcal_update_po_file() {
474
  /*
475
  * Due to the introduction of language packs through translate.wordpress.org, loading our textdomain is complex.
476
  *
478
  */
479
  $domain = 'woocommerce-abandoned-cart';
480
  $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
481
+ $loaded = load_textdomain( $domain, trailingslashit( WP_LANG_DIR ) . $domain . '-' . $locale . '.mo' );
482
+ if ( $loaded ) {
483
  return $loaded;
484
  } else {
485
+ load_plugin_textdomain( $domain, false, basename( dirname( __FILE__ ) ) . '/i18n/languages/' );
486
  }
487
  }
488
 
489
  /**
490
  * It will create the plugin tables & the options reqired for plugin.
491
+ *
492
  * @hook register_activation_hook
493
  * @globals mixed $wpdb
494
  * @since 1.0
495
  */
496
  public static function wcal_activate() {
497
 
498
+ // check whether its a multi site install or a single site install.
499
  if ( is_multisite() ) {
500
+
501
  $blog_list = get_sites();
502
  foreach ( $blog_list as $blog_list_key => $blog_list_value ) {
503
+ if ( $blog_list_value->blog_id > 1 ) { // child sites.
504
  $blog_id = $blog_list_value->blog_id;
505
  self::wcal_process_activate( $blog_id );
506
+ } else { // parent site.
507
  self::wcal_process_activate();
508
  }
509
  }
510
+ } else { // single site.
511
  self::wcal_process_activate();
512
  }
513
  }
532
  public static function wcal_process_activate( $blog_id = 0 ) {
533
  global $wpdb;
534
 
535
+ $db_prefix = ( 0 === $blog_id ) ? $wpdb->prefix : $wpdb->prefix . $blog_id . '_';
536
 
537
  $wcap_collate = '';
538
  if ( $wpdb->has_cap( 'collation' ) ) {
539
  $wcap_collate = $wpdb->get_charset_collate();
540
  }
541
+ $table_name = $db_prefix . 'ac_email_templates_lite';
542
+ $wpdb->query( // phpcs:ignore
543
+ "CREATE TABLE IF NOT EXISTS $table_name (
544
+ `id` int(11) NOT NULL AUTO_INCREMENT,
545
+ `subject` text NOT NULL,
546
+ `body` mediumtext NOT NULL,
547
+ `is_active` enum('0','1') NOT NULL,
548
+ `frequency` int(11) NOT NULL,
549
+ `day_or_hour` enum('Days','Hours') NOT NULL,
550
+ `template_name` text NOT NULL,
551
+ `is_wc_template` enum('0','1') NOT NULL,
552
+ `default_template` int(11) NOT NULL,
553
+ `wc_email_header` varchar(50) NOT NULL,
554
+ PRIMARY KEY (`id`)
555
+ ) $wcap_collate AUTO_INCREMENT=1"
556
+ );
557
+
558
+ $sent_table_name = $db_prefix . 'ac_sent_history_lite';
559
+ $wpdb->query( // phpcs:ignore
560
+ "CREATE TABLE IF NOT EXISTS $sent_table_name (
561
+ `id` int(11) NOT NULL auto_increment,
562
+ `template_id` varchar(40) collate utf8_unicode_ci NOT NULL,
563
+ `abandoned_order_id` int(11) NOT NULL,
564
+ `sent_time` datetime NOT NULL,
565
+ `sent_email_id` text COLLATE utf8_unicode_ci NOT NULL,
566
+ PRIMARY KEY (`id`)
567
+ ) $wcap_collate AUTO_INCREMENT=1 "
568
+ );
569
+
570
+ $ac_history_table_name = $db_prefix . 'ac_abandoned_cart_history_lite';
571
+ $wpdb->query( // phpcs:ignore
572
+ "CREATE TABLE IF NOT EXISTS $ac_history_table_name (
573
+ `id` int(11) NOT NULL AUTO_INCREMENT,
574
+ `user_id` int(11) NOT NULL,
575
+ `abandoned_cart_info` text COLLATE utf8_unicode_ci NOT NULL,
576
+ `abandoned_cart_time` int(11) NOT NULL,
577
+ `cart_ignored` enum('0','1') COLLATE utf8_unicode_ci NOT NULL,
578
+ `recovered_cart` int(11) NOT NULL,
579
+ `user_type` text,
580
+ `unsubscribe_link` enum('0','1') COLLATE utf8_unicode_ci NOT NULL,
581
+ `session_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
582
+ `email_reminder_status` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
  PRIMARY KEY (`id`)
584
+ ) $wcap_collate"
585
+ );
586
+
587
+ $guest_table = $db_prefix . 'ac_guest_abandoned_cart_history_lite';
588
+ $result_guest_table = $wpdb->get_results( // phpcs:ignore
589
+ "SHOW TABLES LIKE '$guest_table'"
590
+ );
591
+
592
+ if ( 0 === count( $result_guest_table ) ) {
593
+ $ac_guest_history_table_name = $db_prefix . 'ac_guest_abandoned_cart_history_lite';
594
+ $wpdb->query( // phpcs:ignore
595
+ "CREATE TABLE IF NOT EXISTS $ac_guest_history_table_name (
596
+ `id` int(15) NOT NULL AUTO_INCREMENT,
597
+ `billing_first_name` text,
598
+ `billing_last_name` text,
599
+ `billing_company_name` text,
600
+ `billing_address_1` text,
601
+ `billing_address_2` text,
602
+ `billing_city` text,
603
+ `billing_county` text,
604
+ `billing_zipcode` text,
605
+ `email_id` text,
606
+ `phone` text,
607
+ `ship_to_billing` text,
608
+ `order_notes` text,
609
+ `shipping_first_name` text,
610
+ `shipping_last_name` text,
611
+ `shipping_company_name` text,
612
+ `shipping_address_1` text,
613
+ `shipping_address_2` text,
614
+ `shipping_city` text,
615
+ `shipping_county` text,
616
+ `shipping_zipcode` double,
617
+ `shipping_charges` double,
618
+ PRIMARY KEY (`id`)
619
+ ) $wcap_collate AUTO_INCREMENT=63000000"
620
+ );
621
  }
622
 
623
+ // Default templates - function call to create default templates.
624
+ $check_table_empty = $wpdb->get_var( 'SELECT COUNT(*) FROM `' . $db_prefix . 'ac_email_templates_lite`' ); // phpcs:ignore
625
 
626
  /**
627
  * This is add for thos user who Install the plguin first time.
628
  * So for them this option will be cheked.
629
  */
630
+ if ( 0 === $blog_id ) {
631
  if ( ! get_option( 'wcal_new_default_templates' ) ) {
632
+ if ( 0 === $check_table_empty ) {
633
+ $default_template = new Wcal_Default_Template_Settings();
634
  $default_template->wcal_create_default_templates( $db_prefix, $blog_id );
635
  }
636
  }
637
+ if ( ! get_option( 'ac_lite_cart_abandoned_time' ) ) {
638
+ add_option( 'ac_lite_cart_abandoned_time', 10 );
639
+ }
640
  if ( ! get_option( 'ac_lite_track_guest_cart_from_cart_page' ) ) {
641
  add_option( 'ac_lite_track_guest_cart_from_cart_page', 'on' );
642
  }
658
  $default_template->wcal_create_default_templates( $db_prefix, $blog_id );
659
  }
660
  }
661
+ if ( ! get_blog_option( $blog_id, 'ac_lite_cart_abandoned_time' ) ) {
662
+ add_blog_option( $blog_id, 'ac_lite_cart_abandoned_time', 10 );
663
+ }
664
  if ( ! get_blog_option( $blog_id, 'ac_lite_track_guest_cart_from_cart_page' ) ) {
665
  add_blog_option( $blog_id, 'ac_lite_track_guest_cart_from_cart_page', 'on' );
666
  }
671
  if ( ! get_blog_option( $blog_id, 'wcal_from_email' ) ) {
672
  add_blog_option( $blog_id, 'wcal_from_email', $wcal_get_admin_email );
673
  }
674
+
675
  if ( ! get_blog_option( $blog_id, 'wcal_reply_email' ) ) {
676
  add_blog_option( $blog_id, 'wcal_reply_email', $wcal_get_admin_email );
677
  }
681
 
682
  /**
683
  * It will add the section, field, & registres the plugin fields using Settings API.
684
+ *
685
  * @hook admin_init
686
  * @since 2.5
687
  */
688
+ public function wcal_initialize_plugin_options() {
689
 
690
+ // First, we register a section. This is necessary since all future options must belong to a section.
691
  add_settings_section(
692
+ 'ac_lite_general_settings_section', // ID used to identify this section and with which to register options.
693
+ __( 'Settings', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page.
694
+ array( $this, 'ac_lite_general_options_callback' ), // Callback used to render the description of the section.
695
+ 'woocommerce_ac_page' // Page on which to add this section of options.
696
  );
697
 
698
  add_settings_field(
701
  array( $this, 'wcal_enable_cart_emails_callback' ),
702
  'woocommerce_ac_page',
703
  'ac_lite_general_settings_section',
704
+ array( __( 'Yes, enable the abandoned cart emails.', 'woocommerce-abandoned-cart' ) )
705
  );
706
 
707
  add_settings_field(
722
  array( __( 'Automatically delete abandoned cart orders after X days.', 'woocommerce-abandoned-cart' ) )
723
  );
724
 
 
725
  add_settings_field(
726
  'ac_lite_email_admin_on_recovery',
727
  __( 'Email admin On Order Recovery', 'woocommerce-abandoned-cart' ),
731
  array( __( 'Sends email to Admin if an Abandoned Cart Order is recovered.', 'woocommerce-abandoned-cart' ) )
732
  );
733
 
 
734
  add_settings_field(
735
+ 'ac_lite_track_guest_cart_from_cart_page',
736
+ __( 'Start tracking from Cart Page', 'woocommerce-abandoned-cart' ),
737
+ array( $this, 'wcal_track_guest_cart_from_cart_page_callback' ),
738
+ 'woocommerce_ac_page',
739
+ 'ac_lite_general_settings_section',
740
+ array( __( 'Enable tracking of abandoned products & carts even if customer does not visit the checkout page or does not enter any details on the checkout page like Name or Email. Tracking will begin as soon as a visitor adds a product to their cart and visits the cart page.', 'woocommerce-abandoned-cart' ) )
741
  );
742
 
743
  add_settings_field(
766
  'ac_lite_general_settings_section',
767
  array( __( '<br>In compliance with GDPR, allow the site visitor (guests & registered users) to opt out from cart tracking. This message will be displayed in conjunction with the GDPR message above.</i>', 'woocommerce-abandoned-cart' ) )
768
  );
769
+
770
  add_settings_field(
771
  'wcal_gdpr_opt_out_message',
772
  __( 'Message to be displayed when the user chooses to opt out of cart tracking.', 'woocommerce-abandoned-cart' ),
778
 
779
  /**
780
  * New section for the Adding the abandoned cart setting.
781
+ *
782
  * @since 4.7
783
  */
 
784
  add_settings_section(
785
+ 'ac_email_settings_section', // ID used to identify this section and with which to register options.
786
+ __( 'Settings for abandoned cart recovery emails', 'woocommerce-abandoned-cart' ), // Title to be displayed on the administration page.
787
+ array( $this, 'wcal_email_callback' ), // Callback used to render the description of the section.
788
+ 'woocommerce_ac_email_page' // Page on which to add this section of options.
789
  );
790
 
791
  add_settings_field(
792
+ 'wcal_from_name',
793
+ __( '"From" Name', 'woocommerce-abandoned-cart' ),
794
+ array( $this, 'wcal_from_name_callback' ),
795
+ 'woocommerce_ac_email_page',
796
+ 'ac_email_settings_section',
797
+ array( 'Enter the name that should appear in the email sent.', 'woocommerce-abandoned-cart' )
798
  );
799
 
800
  add_settings_field(
801
+ 'wcal_from_email',
802
+ __( '"From" Address', 'woocommerce-abandoned-cart' ),
803
+ array( $this, 'wcal_from_email_callback' ),
804
+ 'woocommerce_ac_email_page',
805
+ 'ac_email_settings_section',
806
+ array( 'Email address from which the reminder emails should be sent.', 'woocommerce-abandoned-cart' )
807
  );
808
 
809
  add_settings_field(
810
+ 'wcal_reply_email',
811
+ __( 'Send Reply Emails to', 'woocommerce-abandoned-cart' ),
812
+ array( $this, 'wcal_reply_email_callback' ),
813
+ 'woocommerce_ac_email_page',
814
+ 'ac_email_settings_section',
815
+ array( 'When a contact receives your email and clicks reply, which email address should that reply be sent to?', 'woocommerce-abandoned-cart' )
816
  );
817
 
818
+ // Finally, we register the fields with WordPress.
819
  register_setting(
820
  'woocommerce_ac_settings',
821
  'wcal_enable_cart_emails'
824
  register_setting(
825
  'woocommerce_ac_settings',
826
  'ac_lite_cart_abandoned_time',
827
+ array( $this, 'ac_lite_cart_time_validation' )
828
  );
829
 
830
  register_setting(
831
  'woocommerce_ac_settings',
832
  'ac_lite_delete_abandoned_order_days',
833
+ array( $this, 'wcal_delete_days_validation' )
834
  );
835
 
836
  register_setting(
866
  register_setting(
867
  'woocommerce_ac_email_settings',
868
  'wcal_from_name'
869
+ );
870
  register_setting(
871
  'woocommerce_ac_email_settings',
872
  'wcal_from_email'
876
  'wcal_reply_email'
877
  );
878
 
879
+ do_action( 'wcal_add_new_settings' );
880
  }
881
 
882
  /**
883
  * Settings API callback for section "ac_lite_general_settings_section".
884
+ *
885
  * @since 2.5
886
  */
887
+ public function ac_lite_general_options_callback() {
 
888
  }
889
 
890
  /**
891
+ * Settings API callback for the enable cart reminder emails.
892
+ *
893
+ * @param array $args - Arguments.
894
  * @since 5.5
895
  */
896
  public static function wcal_enable_cart_emails_callback( $args ) {
897
 
898
+ $enable_cart_emails = get_option( 'wcal_enable_cart_emails', '' );
899
 
900
+ if ( isset( $enable_cart_emails ) && '' === $enable_cart_emails ) {
901
  $enable_cart_emails = 'off';
902
  }
903
+ printf(
904
+ '<input type="checkbox" id="wcal_enable_cart_emails" name="wcal_enable_cart_emails" value="on" ' . checked( 'on', $enable_cart_emails, false ) . ' />'
905
+ );
906
+ $html = '<label for="wcal_enable_cart_emails"> ' . $args[0] . '</label>';
907
+ echo wp_kses_post( $html );
908
  }
909
 
910
  /**
911
  * Settings API callback for cart time field.
912
+ *
913
+ * @param array $args Arguments.
914
  * @since 2.5
915
  */
916
+ public function ac_lite_cart_abandoned_time_callback( $args ) {
917
+ // First, we read the option.
918
  $cart_abandoned_time = get_option( 'ac_lite_cart_abandoned_time' );
919
+ // Next, we update the name attribute to access this element's ID in the context of the display options array.
920
+ // We also access the show_header element of the options collection in the call to the checked() helper function.
921
  printf(
922
+ '<input type="text" id="ac_lite_cart_abandoned_time" name="ac_lite_cart_abandoned_time" value="%s" />',
923
+ isset( $cart_abandoned_time ) ? esc_attr( $cart_abandoned_time ) : ''
924
+ );
925
+ // Here, we'll take the first argument of the array and add it to a label next to the checkbox.
926
+ $html = '<label for="ac_lite_cart_abandoned_time"> ' . $args[0] . '</label>';
927
+ echo wp_kses_post( $html );
928
  }
929
 
930
  /**
931
  * Settings API cart time field validation.
932
+ *
933
+ * @param int|string $input - Input to be validated.
934
+ * @return int|string $output - Validated output.
935
  * @since 2.5
936
  */
937
+ public function ac_lite_cart_time_validation( $input ) {
938
  $output = '';
939
+ if ( '' != $input && ( is_numeric( $input ) && $input > 0 ) ) {
940
+ $output = stripslashes( $input );
941
  } else {
942
  add_settings_error( 'ac_lite_cart_abandoned_time', 'error found', __( 'Abandoned cart cut off time should be numeric and has to be greater than 0.', 'woocommerce-abandoned-cart' ) );
943
  }
946
 
947
  /**
948
  * Validation for automatically delete abandoned carts after X days.
949
+ *
950
+ * @param int | string $input input of the field Abandoned cart cut off time.
951
+ * @return int | string $output Error message or the input value.
952
  * @since 5.0
953
  */
954
  public static function wcal_delete_days_validation( $input ) {
963
 
964
  /**
965
  * Callback for deleting abandoned order after X days field.
966
+ *
967
+ * @param array $args Argument given while adding the field.
968
  * @since 5.0
969
  */
970
  public static function wcal_delete_abandoned_orders_days_callback( $args ) {
971
+ // First, we read the option.
972
  $delete_abandoned_order_days = get_option( 'ac_lite_delete_abandoned_order_days' );
973
+ // Next, we update the name attribute to access this element's ID in the context of the display options array.
974
+ // We also access the show_header element of the options collection in the call to the checked() helper function.
975
  printf(
976
  '<input type="text" id="ac_lite_delete_abandoned_order_days" name="ac_lite_delete_abandoned_order_days" value="%s" />',
977
  isset( $delete_abandoned_order_days ) ? esc_attr( $delete_abandoned_order_days ) : ''
978
  );
979
+ // Here, we'll take the first argument of the array and add it to a label next to the checkbox.
980
  $html = '<label for="ac_lite_delete_abandoned_order_days"> ' . $args[0] . '</label>';
981
+ echo wp_kses_post( $html );
982
  }
983
 
984
  /**
985
  * Settings API callback for email admin on cart recovery field.
986
+ *
987
+ * @param array $args Arguments.
988
  * @since 2.5
989
  */
990
+ public function ac_lite_email_admin_on_recovery( $args ) {
991
+ // First, we read the option.
992
  $email_admin_on_recovery = get_option( 'ac_lite_email_admin_on_recovery' );
993
 
994
  // This condition added to avoid the notie displyed while Check box is unchecked.
995
  if ( isset( $email_admin_on_recovery ) && '' == $email_admin_on_recovery ) {
996
  $email_admin_on_recovery = 'off';
997
  }
998
+ // Next, we update the name attribute to access this element's ID in the context of the display options array.
999
+ // We also access the show_header element of the options collection in the call to the checked() helper function.
1000
+ $html = '';
1001
  printf(
1002
+ '<input type="checkbox" id="ac_lite_email_admin_on_recovery" name="ac_lite_email_admin_on_recovery" value="on"
1003
+ ' . checked( 'on', $email_admin_on_recovery, false ) . ' />'
1004
  );
1005
 
1006
+ // Here, we'll take the first argument of the array and add it to a label next to the checkbox.
1007
  $html .= '<label for="ac_lite_email_admin_on_recovery"> ' . $args[0] . '</label>';
1008
+ echo wp_kses_post( $html );
1009
  }
1010
+
1011
  /**
1012
  * Settings API callback for capturing guest cart which do not reach the checkout page.
1013
+ *
1014
+ * @param array $args Arguments.
1015
  * @since 2.7
1016
  */
1017
+ public function wcal_track_guest_cart_from_cart_page_callback( $args ) {
1018
+ // First, we read the option.
1019
+ $disable_guest_cart_from_cart_page = get_option( 'ac_lite_track_guest_cart_from_cart_page', '' );
1020
 
1021
  // This condition added to avoid the notice displyed while Check box is unchecked.
1022
+ if ( isset( $disable_guest_cart_from_cart_page ) && '' === $disable_guest_cart_from_cart_page ) {
1023
  $disable_guest_cart_from_cart_page = 'off';
1024
  }
1025
+ // Next, we update the name attribute to access this element's ID in the context of the display options array.
1026
+ // We also access the show_header element of the options collection in the call to the checked() helper function.
1027
+ $html = '';
1028
 
1029
  printf(
1030
+ '<input type="checkbox" id="ac_lite_track_guest_cart_from_cart_page" name="ac_lite_track_guest_cart_from_cart_page" value="on"
1031
+ ' . checked( 'on', $disable_guest_cart_from_cart_page, false ) . ' />'
1032
+ );
1033
+ // Here, we'll take the first argument of the array and add it to a label next to the checkbox.
1034
  $html .= '<label for="ac_lite_track_guest_cart_from_cart_page"> ' . $args[0] . '</label>';
1035
+ echo wp_kses_post( $html );
1036
  }
1037
 
1038
  /**
1039
  * Call back function for guest user cart capture message
1040
+ *
1041
+ * @param array $args Argument for adding field details.
1042
  * @since 7.8
1043
  */
1044
  public static function wcal_guest_cart_capture_msg_callback( $args ) {
1045
 
1046
  $guest_msg = get_option( 'wcal_guest_cart_capture_msg' );
1047
 
1048
+ printf(
1049
+ "<textarea rows='4' cols='80' id='wcal_guest_cart_capture_msg' name='wcal_guest_cart_capture_msg'>" . htmlspecialchars( $guest_msg, ENT_QUOTES ) . '</textarea>' // phpcs:ignore
1050
+ );
1051
 
1052
+ $html = '<label for="wcal_guest_cart_capture_msg"> ' . $args[0] . '</label>';
1053
+ echo wp_kses_post( $html );
1054
  }
1055
 
1056
  /**
1057
  * Call back function for registered user cart capture message
1058
+ *
1059
+ * @param array $args Argument for adding field details.
1060
  * @since 7.8
1061
  */
1062
  public static function wcal_logged_cart_capture_msg_callback( $args ) {
1063
 
1064
  $logged_msg = get_option( 'wcal_logged_cart_capture_msg' );
1065
 
1066
+ printf(
1067
+ "<input type='text' class='regular-text' id='wcal_logged_cart_capture_msg' name='wcal_logged_cart_capture_msg' value='" . htmlspecialchars( $logged_msg, ENT_QUOTES ) . "' />" // phpcs:ignore
1068
+ );
1069
 
1070
+ $html = '<label for="wcal_logged_cart_capture_msg"> ' . $args[0] . '</label>';
1071
+ echo wp_kses_post( $html );
1072
  }
1073
 
1074
 
1075
  /**
1076
+ * Text to allow the user the choice to opt out of cart tracking.
1077
+ *
1078
+ * @param array $args - Arguments.
1079
  * @since 5.5
1080
  */
1081
  public static function wcal_gdpr_allow_opt_out_callback( $args ) {
1082
+
1083
  $wcal_gdpr_allow_opt_out = get_option( 'wcal_gdpr_allow_opt_out' );
1084
+
1085
+ printf(
1086
+ "<input type='text' class='regular-text' id='wcal_gdpr_allow_opt_out' name='wcal_gdpr_allow_opt_out' value='" . htmlspecialchars( $wcal_gdpr_allow_opt_out, ENT_QUOTES ) . "' />" // phpcs:ignore
1087
+ );
1088
+
1089
+ $html = '<label for="wcal_gdpr_allow_opt_out"> ' . $args[0] . '</label>';
1090
+ echo wp_kses_post( $html );
1091
  }
1092
 
1093
  /**
1094
  * Message to display when the user chooses to opt out of cart tracking.
1095
+ *
1096
+ * @param array $args - Arguments.
1097
  * @since 5.5
1098
  */
1099
  public static function wcal_gdpr_opt_out_msg_callback( $args ) {
1100
+
1101
  $wcal_gdpr_opt_out_message = get_option( 'wcal_gdpr_opt_out_message' );
1102
+
1103
+ printf(
1104
+ "<input type='text' class='regular-text' id='wcal_gdpr_opt_out_message' name='wcal_gdpr_opt_out_message' value='" . htmlspecialchars( $wcal_gdpr_opt_out_message, ENT_QUOTES ) . "' />" // phpcs:ignore
1105
+ );
1106
+
1107
+ $html = '<label for="wcal_gdpr_opt_out_message"> ' . $args[0] . '</label>';
1108
+ echo wp_kses_post( $html );
1109
  }
1110
 
1111
  /**
1112
  * Settings API callback for Abandoned cart email settings of the plugin.
1113
+ *
1114
  * @since 3.5
1115
  */
1116
+ public function wcal_email_callback() {
 
1117
  }
1118
 
1119
  /**
1120
  * Settings API callback for from name used in Abandoned cart email.
1121
+ *
1122
+ * @param array $args Arguments.
1123
  * @since 3.5
1124
  */
1125
  public static function wcal_from_name_callback( $args ) {
1126
+ // First, we read the option.
1127
  $wcal_from_name = get_option( 'wcal_from_name' );
1128
+ // Next, we update the name attribute to access this element's ID in the context of the display options array.
1129
+ // We also access the show_header element of the options collection in the call to the checked() helper function.
1130
  printf(
1131
+ '<input type="text" id="wcal_from_name" name="wcal_from_name" value="%s" />',
1132
+ isset( $wcal_from_name ) ? esc_attr( $wcal_from_name ) : ''
1133
  );
1134
+ // Here, we'll take the first argument of the array and add it to a label next to the checkbox.
1135
+ $html = '<label for="wcal_from_name_label"> ' . $args[0] . '</label>';
1136
+ echo wp_kses_post( $html );
1137
  }
1138
 
1139
  /**
1140
  * Settings API callback for from email used in Abandoned cart email.
1141
+ *
1142
+ * @param array $args Arguments.
1143
  * @since 3.5
1144
  */
1145
  public static function wcal_from_email_callback( $args ) {
1146
+ // First, we read the option.
1147
  $wcal_from_email = get_option( 'wcal_from_email' );
1148
+ // Next, we update the name attribute to access this element's ID in the context of the display options array.
1149
+ // We also access the show_header element of the options collection in the call to the checked() helper function.
1150
  printf(
1151
+ '<input type="text" id="wcal_from_email" name="wcal_from_email" value="%s" />',
1152
+ isset( $wcal_from_email ) ? esc_attr( $wcal_from_email ) : ''
1153
  );
1154
+ // Here, we'll take the first argument of the array and add it to a label next to the checkbox.
1155
+ $html = '<label for="wcal_from_email_label"> ' . $args[0] . '</label>';
1156
+ echo wp_kses_post( $html );
1157
  }
1158
 
1159
  /**
1160
  * Settings API callback for reply email used in Abandoned cart email.
1161
+ *
1162
+ * @param array $args Arguments.
1163
  * @since 3.5
1164
  */
1165
  public static function wcal_reply_email_callback( $args ) {
1166
+ // First, we read the option.
1167
  $wcal_reply_email = get_option( 'wcal_reply_email' );
1168
+ // Next, we update the name attribute to access this element's ID in the context of the display options array.
1169
+ // We also access the show_header element of the options collection in the call to the checked() helper function.
1170
  printf(
1171
+ '<input type="text" id="wcal_reply_email" name="wcal_reply_email" value="%s" />',
1172
+ isset( $wcal_reply_email ) ? esc_attr( $wcal_reply_email ) : ''
1173
  );
1174
+ // Here, we'll take the first argument of the array and add it to a label next to the checkbox.
1175
+ $html = '<label for="wcal_reply_email_label"> ' . $args[0] . '</label>';
1176
+ echo wp_kses_post( $html );
1177
+ }
1178
 
1179
  /**
1180
  * Add a submenu page under the WooCommerce.
1181
+ *
1182
  * @hook admin_menu
1183
  * @since 1.0
1184
  */
1185
+ public function wcal_admin_menu() {
1186
+ $page = add_submenu_page( 'woocommerce', __( 'Abandoned Carts', 'woocommerce-abandoned-cart' ), __( 'Abandoned Carts', 'woocommerce-abandoned-cart' ), 'manage_woocommerce', 'woocommerce_ac_page', array( &$this, 'wcal_menu_page' ) );
1187
  }
1188
 
1189
  /**
1190
  * Capture the cart and insert the information of the cart into DataBase.
1191
+ *
1192
  * @hook woocommerce_cart_updated
1193
  * @globals mixed $wpdb
1194
  * @globals mixed $woocommerce
1195
  * @since 1.0
1196
  */
1197
+ public function wcal_store_cart_timestamp() {
1198
 
1199
  $block_crawlers = apply_filters( 'wcal_block_crawlers', false );
1200
 
1218
  $cart_ignored = 0;
1219
  $recovered_cart = 0;
1220
 
1221
+ $track_guest_user_cart_from_cart = '';
1222
  if ( isset( $track_guest_cart_from_cart_page ) ) {
1223
  $track_guest_user_cart_from_cart = $track_guest_cart_from_cart_page;
1224
  }
1232
 
1233
  if ( is_user_logged_in() ) {
1234
 
1235
+ $user_id = get_current_user_id();
1236
  $gdpr_consent = get_user_meta( $user_id, 'wcal_gdpr_tracking_choice', true );
1237
 
1238
+ if ( '' === $gdpr_consent ) {
1239
  $gdpr_consent = true;
1240
  }
1241
 
1242
  $wcal_user_restricted = false;
1243
  $wcal_user_restricted = apply_filters( 'wcal_restrict_user', $wcal_user_restricted, $user_id );
 
 
 
 
 
 
 
 
1244
 
1245
+ if ( $gdpr_consent && ! $wcal_user_restricted ) {
 
 
 
1246
 
1247
+ $results = $wpdb->get_results( // phpcs:ignore
1248
+ $wpdb->prepare(
1249
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = %s AND recovered_cart = %s',
1250
+ $user_id,
1251
+ $cart_ignored,
1252
+ $recovered_cart
1253
+ )
1254
+ );
1255
+ if ( 0 === count( $results ) ) {
1256
  $cart_info_meta = array();
1257
  $cart_info_meta['cart'] = WC()->session->cart;
1258
+ $cart_info_meta = wp_json_encode( $cart_info_meta );
1259
 
1260
+ if ( '' !== $cart_info_meta && '{"cart":[]}' != $cart_info_meta && '""' !== $cart_info_meta ) {
1261
  $cart_info = $cart_info_meta;
1262
+ $user_type = 'REGISTERED';
1263
+ $wpdb->query( //phpcs:ignore
1264
+ $wpdb->prepare(
1265
+ 'INSERT INTO `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` ( user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type ) VALUES ( %d, %s, %d, %s, %s )',
1266
+ $user_id,
1267
+ $cart_info,
1268
+ $current_time,
1269
+ $cart_ignored,
1270
+ $user_type
1271
+ )
1272
+ );
1273
  $abandoned_cart_id = $wpdb->insert_id;
1274
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
1275
  }
1276
  } elseif ( isset( $results[0]->abandoned_cart_time ) && $compare_time > $results[0]->abandoned_cart_time ) {
 
 
 
1277
  $updated_cart_info = array();
1278
  $updated_cart_info['cart'] = WC()->session->cart;
1279
+ $updated_cart_info = wp_json_encode( $updated_cart_info );
1280
 
1281
  if ( ! $this->wcal_compare_carts( $user_id, $results[0]->abandoned_cart_info ) ) {
1282
  $updated_cart_ignored = 1;
1283
+ $wpdb->query( //phpcs:ignore
1284
+ $wpdb->prepare(
1285
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET cart_ignored = %s WHERE user_id = %d',
1286
+ $updated_cart_ignored,
1287
+ $user_id
1288
+ )
1289
+ );
1290
+ $user_type = 'REGISTERED';
1291
+ $wpdb->query( //phpcs:ignore
1292
+ $wpdb->prepare(
1293
+ 'INSERT INTO `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` (user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type) VALUES (%d, %s, %d, %s, %s)',
1294
+ $user_id,
1295
+ $updated_cart_info,
1296
+ $current_time,
1297
+ $cart_ignored,
1298
+ $user_type
1299
+ )
1300
+ );
1301
+ update_user_meta( $user_id, '_woocommerce_ac_modified_cart', md5( 'yes' ) );
1302
 
1303
+ $abandoned_cart_id = $wpdb->insert_id;
1304
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
1305
  } else {
1306
+ update_user_meta( $user_id, '_woocommerce_ac_modified_cart', md5( 'no' ) );
1307
  }
1308
  } else {
 
 
 
1309
  $updated_cart_info = array();
1310
  $updated_cart_info['cart'] = WC()->session->cart;
1311
+ $updated_cart_info = wp_json_encode( $updated_cart_info );
1312
+
1313
+ $wpdb->query( //phpcs:ignore
1314
+ $wpdb->prepare(
1315
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET abandoned_cart_info = %s, abandoned_cart_time = %d WHERE user_id = %d AND cart_ignored = %s',
1316
+ $updated_cart_info,
1317
+ $current_time,
1318
+ $user_id,
1319
+ $cart_ignored
1320
+ )
1321
+ );
1322
+
1323
+ $get_abandoned_record = $wpdb->get_results( //phpcs:ignore
1324
+ $wpdb->prepare(
1325
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = %s',
1326
+ $user_id,
1327
+ 0
1328
+ )
1329
+ );
1330
 
1331
  if ( count( $get_abandoned_record ) > 0 ) {
1332
+ $abandoned_cart_id = $get_abandoned_record[0]->id;
1333
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
1334
  }
1335
  }
1336
  }
1337
  } else {
1338
+ // start here guest user.
1339
  $user_id = wcal_common::wcal_get_cart_session( 'user_id' );
1340
 
1341
  // GDPR consent.
1342
+ $gdpr_consent = true;
1343
  $show_gdpr_msg = wcal_common::wcal_get_cart_session( 'wcal_cart_tracking_refused' );
1344
  if ( isset( $show_gdpr_msg ) && 'yes' === $show_gdpr_msg ) {
1345
  $gdpr_consent = false;
1346
  }
1347
 
1348
  if ( $gdpr_consent ) {
1349
+ $results = $wpdb->get_results( //phpcs:ignore
1350
+ $wpdb->prepare(
1351
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d AND cart_ignored = %s AND recovered_cart = %s AND user_id != %s',
1352
+ $user_id,
1353
+ 0,
1354
+ 0,
1355
+ 0
1356
+ )
1357
+ );
1358
  $cart = array();
1359
 
1360
  $get_cookie = WC()->session->get_customer_id();
1361
 
1362
+ if ( function_exists( 'WC' ) ) {
1363
  $cart['cart'] = WC()->session->cart;
1364
  } else {
1365
  $cart['cart'] = $woocommerce->session->cart;
1366
  }
1367
 
1368
+ $updated_cart_info = wp_json_encode( $cart );
 
1369
 
1370
  if ( count( $results ) > 0 && '{"cart":[]}' != $updated_cart_info ) {
1371
  if ( $compare_time > $results[0]->abandoned_cart_time ) {
1372
  if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {
1373
 
1374
+ $wpdb->query( //phpcs:ignore
1375
+ $wpdb->prepare(
1376
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET cart_ignored = %s WHERE user_id = %s',
1377
+ 1,
1378
+ $user_id
1379
+ )
1380
+ );
1381
+ $user_type = 'GUEST';
1382
+ $wpdb->query( //phpcs:ignore
1383
+ $wpdb->prepare(
1384
+ 'INSERT INTO `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` (user_id, abandoned_cart_info, abandoned_cart_time, cart_ignored, user_type) VALUES (%d, %s, %d, %s, %s)',
1385
+ $user_id,
1386
+ $updated_cart_info,
1387
+ $current_time,
1388
+ $cart_ignored,
1389
+ $user_type
1390
+ )
1391
+ );
1392
+ update_user_meta( $user_id, '_woocommerce_ac_modified_cart', md5( 'yes' ) );
1393
  } else {
1394
+ update_user_meta( $user_id, '_woocommerce_ac_modified_cart', md5( 'no' ) );
1395
  }
1396
  } else {
1397
+ $wpdb->query( //phpcs:ignore
1398
+ $wpdb->prepare(
1399
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET abandoned_cart_info = %s, abandoned_cart_time = %s WHERE user_id = %d AND cart_ignored = %s',
1400
+ $updated_cart_info,
1401
+ $current_time,
1402
+ $user_id,
1403
+ 0
1404
+ )
1405
+ );
1406
  }
1407
  } else {
1408
+ // Here we capture the guest cart from the cart page @since 3.5.
1409
+ if ( 'on' === $track_guest_user_cart_from_cart && isset( $get_cookie ) && '' !== $get_cookie ) {
1410
+ $results = $wpdb->get_results( //phpcs:ignore
1411
+ $wpdb->prepare(
1412
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE session_id LIKE %s AND cart_ignored = %s AND recovered_cart = %s',
1413
+ $get_cookie,
1414
+ 0,
1415
+ 0
1416
+ )
1417
+ );
1418
  if ( 0 == count( $results ) ) {
1419
  $cart_info = $updated_cart_info;
1420
  $blank_cart_info = '[]';
1421
  if ( $blank_cart_info != $cart_info && '{"cart":[]}' != $cart_info ) {
1422
+ $wpdb->query( //phpcs:ignore
1423
+ $wpdb->prepare(
1424
+ 'INSERT INTO `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` ( abandoned_cart_info , abandoned_cart_time , cart_ignored , recovered_cart, user_type, session_id ) VALUES ( %s, %s, %s, %s, %s, %s )',
1425
+ $cart_info,
1426
+ $current_time,
1427
+ 0,
1428
+ 0,
1429
+ 'GUEST',
1430
+ $get_cookie
1431
+ )
1432
+ );
1433
  $abandoned_cart_id = $wpdb->insert_id;
1434
  }
1435
  } elseif ( $compare_time > $results[0]->abandoned_cart_time ) {
1436
  $blank_cart_info = '[]';
1437
  if ( $blank_cart_info != $updated_cart_info && '{"cart":[]}' != $updated_cart_info ) {
1438
  if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {
1439
+ $wpdb->query( // phpcs:ignore
1440
+ $wpdb->prepare(
1441
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET cart_ignored = %s WHERE session_id = %s',
1442
+ 1,
1443
+ $get_cookie
1444
+ )
1445
+ );
1446
+ $wpdb->query( //phpcs:ignore
1447
+ $wpdb->prepare(
1448
+ 'INSERT INTO `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` ( abandoned_cart_info, abandoned_cart_time, cart_ignored, recovered_cart, user_type, session_id ) VALUES ( %s, %s, %s, %s, %s, %s )',
1449
+ $updated_cart_info,
1450
+ $current_time,
1451
+ 0,
1452
+ 0,
1453
+ 'GUEST',
1454
+ $get_cookie
1455
+ )
1456
+ );
1457
  $abandoned_cart_id = $wpdb->insert_id;
1458
  }
1459
  }
1461
  $blank_cart_info = '[]';
1462
  if ( $blank_cart_info != $updated_cart_info && '{"cart":[]}' != $updated_cart_info ) {
1463
  if ( ! $this->wcal_compare_only_guest_carts( $updated_cart_info, $results[0]->abandoned_cart_info ) ) {
1464
+ $wpdb->query( //phpcs:ignore
1465
+ $wpdb->prepare(
1466
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET abandoned_cart_info = %s, abandoned_cart_time = %s WHERE session_id = %s AND cart_ignored = %s',
1467
+ $updated_cart_info,
1468
+ $current_time,
1469
+ $get_cookie,
1470
+ 0
1471
+ )
1472
+ );
1473
  }
1474
  }
1475
  }
1476
+ if ( isset( $abandoned_cart_id ) ) {
1477
+ // add the abandoned id in the session.
1478
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $abandoned_cart_id );
1479
  }
1480
  }
1483
  }
1484
  }
1485
 
1486
+ /**
1487
+ * Detect Crawlers
1488
+ *
1489
+ * @param boolean $ignore - Ignore.
1490
+ * @return boolean $ignore - Ignore.
1491
+ */
1492
+ public function wcal_detect_crawlers( $ignore ) {
1493
+ $user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
1494
 
1495
  if ( '' === $user_agent ) {
1496
  return $ignore;
1497
  }
1498
 
1499
  // Current list of bots being blocked:
1500
+ // 1. Googlebot, BingBot, DuckDuckBot, YandexBot, Exabot.
1501
+ // 2. cURL.
1502
+ // 3. wget.
1503
+ // 4. Yahoo/Slurp.
1504
+ // 5. Baiduspider.
1505
+ // 6. Sogou.
1506
+ // 7. Alexa.
1507
  $bot_agents = array(
1508
  'curl',
1509
  'wget',
1515
  'ia_archiver',
1516
  );
1517
 
1518
+ foreach ( $bot_agents as $url ) {
1519
+ if ( false !== stripos( $user_agent, $url ) ) {
1520
  return true;
1521
  }
1522
  }
1526
 
1527
  /**
1528
  * It will unsubscribe the abandoned cart, so user will not recieve further abandoned cart emails.
1529
+ *
1530
  * @hook template_include
1531
+ * @param string $args Arguments.
1532
+ * @return string $args Arguments.
1533
  * @globals mixed $wpdb
1534
  * @since 2.9
1535
  */
1536
+ public function wcal_email_unsubscribe( $args ) {
1537
  global $wpdb;
1538
 
1539
+ if ( isset( $_GET['wcal_track_unsubscribe'] ) && 'wcal_unsubscribe' === sanitize_text_field( wp_unslash( $_GET['wcal_track_unsubscribe'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1540
+ $encoded_email_id = isset( $_GET['validate'] ) ? rawurldecode( sanitize_text_field( wp_unslash( $_GET['validate'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1541
+ $validate_email_id_string = str_replace( ' ', '+', $encoded_email_id );
1542
  $validate_email_address_string = '';
1543
  $validate_email_id_decode = 0;
1544
+ $crypt_key = get_option( 'wcal_security_key' );
1545
+ $validate_email_id_decode = Wcal_Aes_Ctr::decrypt( $validate_email_id_string, $crypt_key, 256 );
1546
+ if ( isset( $_GET['track_email_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1547
+ $encoded_email_address = rawurldecode( sanitize_text_field( wp_unslash( $_GET['track_email_id'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
1548
+ $validate_email_address_string = str_replace( ' ', '+', $encoded_email_address );
1549
  }
1550
+
1551
+ $results_sent = $wpdb->get_results( //phpcs:ignore
1552
+ $wpdb->prepare(
1553
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_sent_history_lite` WHERE id = %d ',
1554
+ $validate_email_id_decode
1555
+ )
1556
+ );
1557
  $email_address = '';
1558
  if ( isset( $results_sent[0] ) ) {
1559
+ $email_address = $results_sent[0]->sent_email_id;
1560
  }
1561
+ if ( hash( 'sha256', $email_address ) === $validate_email_address_string && '' !== $email_address ) {
1562
  $email_sent_id = $validate_email_id_decode;
1563
+ $get_ac_id_results = $wpdb->get_results( //phpcs:ignore
1564
+ $wpdb->prepare(
1565
+ 'SELECT abandoned_order_id FROM `' . $wpdb->prefix . 'ac_sent_history_lite` WHERE id = %d',
1566
+ $email_sent_id
1567
+ )
1568
+ );
1569
  $user_id = 0;
1570
  if ( isset( $get_ac_id_results[0] ) ) {
1571
+ $get_user_results = $wpdb->get_results( //phpcs:ignore
1572
+ $wpdb->prepare(
1573
+ 'SELECT user_id FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE id = %d',
1574
+ $get_ac_id_results[0]->abandoned_order_id
1575
+ )
1576
+ );
1577
  }
1578
  if ( isset( $get_user_results[0] ) ) {
1579
  $user_id = $get_user_results[0]->user_id;
1580
  }
1581
 
1582
+ $wpdb->query( //phpcs:ignore
1583
+ $wpdb->prepare(
1584
+ 'UPDATE `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` SET unsubscribe_link = %s WHERE user_id= %d AND cart_ignored = %s',
1585
+ 1,
1586
+ $user_id,
1587
+ 0
1588
+ )
1589
+ );
1590
+ echo esc_html( 'Unsubscribed Successfully' );
1591
  sleep( 2 );
1592
  $url = get_option( 'siteurl' );
1593
  ?>
1594
  <script>
1595
+ location.href = "<?php echo esc_url( $url ); ?>";
1596
  </script>
1597
+ <?php
1598
  }
1599
  } else {
1600
+ return $args;
1601
  }
1602
  }
1603
 
1604
  /**
1605
  * It will track the URL of cart link from email, and it will populate the logged-in and guest users cart.
1606
+ *
1607
  * @hook template_include
1608
+ * @param string $template - Template name.
1609
+ * @return string $template - Template name.
1610
  * @globals mixed $wpdb
1611
  * @globals mixed $woocommerce
1612
  * @since 1.0
1613
  */
1614
+ public function wcal_email_track_links( $template ) {
1615
  global $woocommerce;
 
1616
 
1617
+ $track_link = isset( $_GET['wcal_action'] ) ? sanitize_text_field( wp_unslash( $_GET['wcal_action'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1618
+
1619
+ if ( 'track_links' === $track_link ) {
 
1620
  if ( '' === session_id() ) {
1621
+ // session has not started.
1622
  session_start();
1623
  }
1624
  global $wpdb;
1625
+ $validate_server_string = isset( $_GET ['validate'] ) ? rawurldecode( wp_unslash( $_GET ['validate'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1626
+ $validate_server_string = str_replace( ' ', '+', $validate_server_string );
1627
  $validate_encoded_string = $validate_server_string;
1628
+ $crypt_key = get_option( 'wcal_security_key' );
1629
+ $link_decode = Wcal_Aes_Ctr::decrypt( $validate_encoded_string, $crypt_key, 256 );
1630
  $sent_email_id_pos = strpos( $link_decode, '&' );
1631
+ $email_sent_id = substr( $link_decode, 0, $sent_email_id_pos );
1632
 
1633
  wcal_common::wcal_set_cart_session( 'email_sent_id', $email_sent_id );
1634
  set_transient( 'wcal_email_sent_id', $email_sent_id, 5 );
1635
 
1636
+ $url_pos = strpos( $link_decode, '=' );
1637
+ ++$url_pos;
1638
+ $url = substr( $link_decode, $url_pos );
1639
+ $get_ac_id_results = $wpdb->get_results( //phpcs:ignore
1640
+ $wpdb->prepare(
1641
+ 'SELECT abandoned_order_id FROM `' . $wpdb->prefix . 'ac_sent_history_lite` WHERE id = %d',
1642
+ $email_sent_id
1643
+ )
1644
+ );
1645
 
1646
  wcal_common::wcal_set_cart_session( 'abandoned_cart_id_lite', $get_ac_id_results[0]->abandoned_order_id );
1647
  set_transient( 'wcal_abandoned_id', $get_ac_id_results[0]->abandoned_order_id, 5 );
1648
 
1649
+ $get_user_results = array();
1650
  if ( count( $get_ac_id_results ) > 0 ) {
1651
+ $get_user_results = $wpdb->get_results( //phpcs:ignore
1652
+ $wpdb->prepare(
1653
+ 'SELECT user_id FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE id = %d',
1654
+ $get_ac_id_results[0]->abandoned_order_id
1655
+ )
1656
+ );
1657
  }
1658
+ $user_id = isset( $get_user_results ) && count( $get_user_results ) > 0 ? (int) $get_user_results[0]->user_id : 0;
1659
+
1660
+ if ( 0 === $user_id ) {
1661
+ echo esc_html( 'Link expired' );
1662
  exit;
1663
  }
1664
  $user = wp_set_current_user( $user_id );
1665
+ if ( $user_id >= '63000000' ) {
1666
+ $results_guest = $wpdb->get_results( //phpcs:ignore
1667
+ $wpdb->prepare(
1668
+ 'SELECT * from `' . $wpdb->prefix . 'ac_guest_abandoned_cart_history_lite` WHERE id = %d',
1669
+ $user_id
1670
+ )
1671
+ );
1672
+
1673
+ $results = $wpdb->get_results( //phpcs:ignore
1674
+ $wpdb->prepare(
1675
+ 'SELECT recovered_cart FROM `' . $wpdb->prefix . 'ac_abandoned_cart_history_lite` WHERE user_id = %d',
1676
+ $user_id
1677
+ )
1678
+ );
1679
+ if ( $results_guest && '0' == $results[0]->recovered_cart ) { // phpcs:ignore
1680
  wcal_common::wcal_set_cart_session( 'guest_first_name', $results_guest[0]->billing_first_name );
1681
  wcal_common::wcal_set_cart_session( 'guest_last_name', $results_guest[0]->billing_last_name );
1682
  wcal_common::wcal_set_cart_session( 'guest_email', $results_guest[0]->email_id );
1683
  wcal_common::wcal_set_cart_session( 'user_id', $user_id );
1684
  } else {
1685
+ if ( version_compare( $woocommerce->version, '3.0.0', '>=' ) ) {
1686
  wp_safe_redirect( get_permalink( wc_get_page_id( 'shop' ) ) );
1687
  exit;
1688
  } else {
1692
  }
1693
  }
1694
 
1695
+ if ( $user_id < '63000000' ) {
1696
  $user_login = $user->data->user_login;
1697
  wp_set_auth_cookie( $user_id );
1698
+ $my_temp = wc_load_persistent_cart( $user_login, $user );
1699
  do_action( 'wp_login', $user_login, $user );
1700
  if ( isset( $sign_in ) && is_wp_error( $sign_in ) ) {
1701
+ echo esc_html( $sign_in->get_error_message() );
1702
  exit;
1703
  }
1704
+ } else {
1705
  $my_temp = $this->wcal_load_guest_persistent_cart( $user_id );
1706
+ }
1707
 
1708
  if ( $email_sent_id > 0 && is_numeric( $email_sent_id ) ) {
1709
  wp_safe_redirect( $url );
1710
  exit;
1711
  }
1712
+ } else {
1713
  return $template;
1714
+ }
1715
  }
1716
 
1717
  /**
1718
  * When customer clicks on the abandoned cart link and that cart is for the the guest users the it will load the guest
1719
  * user's cart detail.
1720
+ *
1721
  * @globals mixed $woocommerce
1722
  * @since 1.0
1723
  */
1724
+ public function wcal_load_guest_persistent_cart() {
1725
  if ( wcal_common::wcal_get_cart_session( 'user_id' ) != '' ) {
1726
  global $woocommerce;
1727
+ $saved_cart = json_decode( get_user_meta( wcal_common::wcal_get_cart_session( 'user_id' ), '_woocommerce_persistent_cart', true ), true );
1728
+ $c = array();
1729
+
1730
+ $cart_contents_total = 0;
1731
+ $cart_contents_weight = 0;
1732
+ $cart_contents_count = 0;
1733
+ $cart_contents_tax = 0;
1734
+ $total = 0;
1735
+ $subtotal = 0;
1736
+ $subtotal_ex_tax = 0;
1737
+ $tax_total = 0;
1738
  if ( count( $saved_cart ) > 0 ) {
1739
  foreach ( $saved_cart as $key => $value ) {
1740
  foreach ( $value as $a => $b ) {
1755
  $subtotal = $subtotal + $b['line_subtotal'];
1756
  $subtotal_ex_tax = $subtotal_ex_tax + $b['line_subtotal'];
1757
  }
1758
+ $saved_cart_data[ $key ] = $value_new;
1759
+ $woocommerce_cart_hash = $a;
1760
  }
1761
  }
1762
 
1763
  if ( $saved_cart ) {
1764
+ if ( empty( $woocommerce->session->cart ) || ! is_array( $woocommerce->session->cart ) || count( $woocommerce->session->cart ) == 0 ) {
1765
  $woocommerce->session->cart = $saved_cart['cart'];
1766
  $woocommerce->session->cart_contents_total = $cart_contents_total;
1767
  $woocommerce->session->cart_contents_weight = $cart_contents_weight;
1790
 
1791
  /**
1792
  * It will compare only guest users cart while capturing the cart.
1793
+ *
1794
+ * @param json_encode $new_cart New abandoned cart details.
1795
+ * @param json_encode $last_abandoned_cart Old abandoned cart details.
1796
+ * @return boolean true | false.
1797
  * @since 1.0
1798
  */
1799
+ public function wcal_compare_only_guest_carts( $new_cart, $last_abandoned_cart ) {
1800
  $current_woo_cart = array();
1801
  $current_woo_cart = json_decode( stripslashes( $new_cart ), true );
1802
  $abandoned_cart_arr = array();
1803
  $abandoned_cart_arr = json_decode( $last_abandoned_cart, true );
1804
+ $temp_variable = '';
1805
  if ( isset( $current_woo_cart['cart'] ) && isset( $abandoned_cart_arr['cart'] ) ) {
1806
+ if ( count( $current_woo_cart['cart'] ) >= count( $abandoned_cart_arr['cart'] ) ) { // phpcs:ignore
1807
+ // do nothing.
1808
  } else {
1809
  $temp_variable = $current_woo_cart;
1810
  $current_woo_cart = $abandoned_cart_arr;
1811
  $abandoned_cart_arr = $temp_variable;
1812
  }
1813
  if ( is_array( $current_woo_cart ) || is_object( $current_woo_cart ) ) {
1814
+ foreach ( $current_woo_cart as $key => $value ) {
1815
+ foreach ( $value as $item_key => $item_value ) {
1816
  $current_cart_product_id = $item_value['product_id'];
1817
  $current_cart_variation_id = $item_value['variation_id'];
1818
  $current_cart_quantity = $item_value['quantity'];
1819
 
1820
+ if ( isset( $abandoned_cart_arr[ $key ][ $item_key ]['product_id'] ) ) {
1821
+ $abandoned_cart_product_id = $abandoned_cart_arr[ $key ][ $item_key ]['product_id'];
1822
  } else {
1823
+ $abandoned_cart_product_id = '';
1824
  }
1825
+ if ( isset( $abandoned_cart_arr[ $key ][ $item_key ]['variation_id'] ) ) {
1826
+ $abandoned_cart_variation_id = $abandoned_cart_arr[ $key ][ $item_key ]['variation_id'];
1827
  } else {
1828
+ $abandoned_cart_variation_id = '';
1829
  }
1830
+ if ( isset( $abandoned_cart_arr[ $key ][ $item_key ]['quantity'] ) ) {
1831
+ $abandoned_cart_quantity = $abandoned_cart_arr[ $key ][ $item_key ]['quantity'];
1832
  } else {
1833
+ $abandoned_cart_quantity = '';
1834
  }
1835
+ if ( ( $current_cart_product_id != $abandoned_cart_product_id ) ||
1836
  ( $current_cart_variation_id != $abandoned_cart_variation_id ) ||
1837
+ ( $current_cart_quantity != $abandoned_cart_quantity ) ) {
1838
  return false;
1839
  }
1840
  }
1846
 
1847
  /**
1848
  * It will compare only loggedin users cart while capturing the cart.
1849
+ *
1850
+ * @param int | string $user_id User id.
1851
+ * @param json_encode $last_abandoned_cart Old abandoned cart details.
1852
+ * @return boolean true | false.
1853
  * @since 1.0
1854
  */
1855
+ public function wcal_compare_carts( $user_id, $last_abandoned_cart ) {
1856
  global $woocommerce;
1857
+ $current_woo_cart = array();
1858
+ $abandoned_cart_arr = array();
1859
+ $wcal_woocommerce_persistent_cart = version_compare( $woocommerce->version, '3.1.0', '>=' ) ? '_woocommerce_persistent_cart_' . get_current_blog_id() : '_woocommerce_persistent_cart';
1860
+ $current_woo_cart = get_user_meta( $user_id, $wcal_woocommerce_persistent_cart, true );
1861
+ $abandoned_cart_arr = json_decode( $last_abandoned_cart, true );
1862
+ $temp_variable = '';
1863
  if ( isset( $current_woo_cart['cart'] ) && isset( $abandoned_cart_arr['cart'] ) ) {
1864
+ if ( count( $current_woo_cart['cart'] ) >= count( $abandoned_cart_arr['cart'] ) ) { // phpcs:ignore
1865
+ // do nothing.
1866
  } else {
1867
  $temp_variable = $current_woo_cart;
1868
  $current_woo_cart = $abandoned_cart_arr;
1876
  $current_cart_variation_id = $item_value['variation_id'];
1877
  $current_cart_quantity = $item_value['quantity'];
1878
 
1879
+ if ( isset( $abandoned_cart_arr[ $key ][ $item_key ]['product_id'] ) ) {
1880
+ $abandoned_cart_product_id = $abandoned_cart_arr[ $key ][ $item_key ]['product_id'];
1881
  } else {
1882
+ $abandoned_cart_product_id = '';
1883
  }
1884
+ if ( isset( $abandoned_cart_arr[ $key ][ $item_key ]['variation_id'] ) ) {
1885
+ $abandoned_cart_variation_id = $abandoned_cart_arr[ $key ][ $item_key ]['variation_id'];
1886
  } else {
1887
+ $abandoned_cart_variation_id = '';
1888
  }
1889
+ if ( isset( $abandoned_cart_arr[ $key ][ $item_key ]['quantity'] ) ) {
1890
+ $abandoned_cart_quantity = $abandoned_cart_arr[ $key ][ $item_key ]['quantity'];
1891
  } else {
1892
+ $abandoned_cart_quantity = '';
1893
  }
1894
  if ( ( $current_cart_product_id != $abandoned_cart_product_id ) ||
1895
  ( $current_cart_variation_id != $abandoned_cart_variation_id ) ||
1896
+ ( $current_cart_quantity != $abandoned_cart_quantity ) ) {
 
1897
  return false;
1898
  }
1899
  }
1905
 
1906
  /**
1907
  * It will add the wp editor for email body on the email edit page.
1908
+ *
1909
  * @hook admin_init
1910
  * @since 2.6
1911
  */
1912
+ public function wcal_action_admin_init() {
1913
 
1914
+ // only hook up these filters if we're in the admin panel and the current user has permission.
1915
+ // to edit posts and pages.
1916
+ if ( ! isset( $_GET['page'] ) || 'woocommerce_ac_page' !== sanitize_text_field( wp_unslash( $_GET['page'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1917
  return;
1918
  }
1919
  if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
1921
  }
1922
  if ( 'true' == get_user_option( 'rich_editing' ) ) {
1923
  remove_filter( 'the_excerpt', 'wpautop' );
1924
+ add_filter( 'tiny_mce_before_init', array( &$this, 'wcal_format_tiny_mce' ) );
1925
+ add_filter( 'mce_buttons', array( &$this, 'wcal_filter_mce_button' ) );
1926
+ add_filter( 'mce_external_plugins', array( &$this, 'wcal_filter_mce_plugin' ) );
1927
  }
1928
  }
1929
 
1930
  /**
1931
  * It will create a button on the WordPress editor.
1932
+ *
1933
  * @hook mce_buttons
1934
+ * @param array $buttons - List of buttons.
1935
+ * @return array $buttons - List of buttons.
1936
  * @since 2.6
1937
  */
1938
+ public function wcal_filter_mce_button( $buttons ) {
1939
+ // add a separation before our button, here our button's id is abandoncart.
1940
  array_push( $buttons, 'abandoncart', '|' );
1941
  return $buttons;
1942
  }
1943
 
1944
  /**
1945
  * It will add the list for the added extra button.
1946
+ *
1947
  * @hook mce_external_plugins
1948
+ * @param array $plugins - Plugins.
1949
+ * @return array $plugins - Plugins.
1950
  * @since 2.6
1951
  */
1952
+ public function wcal_filter_mce_plugin( $plugins ) {
1953
+ // this plugin file will work the magic of our button.
1954
  $plugins['abandoncart'] = plugin_dir_url( __FILE__ ) . 'assets/js/abandoncart_plugin_button.js';
1955
  return $plugins;
1956
  }
1957
 
1958
  /**
1959
  * It will add the tabs on the Abandoned cart page.
1960
+ *
1961
  * @since 1.0
1962
  */
1963
+ public function wcal_display_tabs() {
1964
 
1965
  $action = '';
1966
  $active_listcart = '';
1969
  $active_stats = '';
1970
  $active_dash = '';
1971
 
1972
+ if ( isset( $_GET['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
1973
+ $action = sanitize_text_field( wp_unslash( $_GET['action'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
1974
  } else {
1975
  $action = '';
1976
  $action = apply_filters( 'wcal_default_tab', $action );
1977
  }
1978
+
1979
+ switch ( $action ) {
1980
  case '':
1981
  case 'dashboard':
1982
  $active_dash = 'nav-tab-active';
2000
  }
2001
 
2002
  ?>
2003
+ <div style="background-image: url('<?php echo esc_url( plugins_url( '/assets/images/ac_tab_icon.png', __FILE__ ) ); ?>') !important;" class="icon32"><br>
2004
  </div>
2005
  <h2 class="nav-tab-wrapper woo-nav-tab-wrapper">
2006
+ <a href="admin.php?page=woocommerce_ac_page&action=dashboard" class="nav-tab
2007
+ <?php
2008
+ if ( isset( $active_dash ) ) {
2009
+ echo esc_attr( $active_dash );
2010
+ }
2011
+ ?>
2012
+ "> <?php esc_html_e( 'Dashboard', 'woocommerce-abandoned-cart' ); ?> </a>
2013
+ <a href="admin.php?page=woocommerce_ac_page&action=listcart" class="nav-tab
2014
+ <?php
2015
+ if ( isset( $active_listcart ) ) {
2016
+ echo esc_attr( $active_listcart );
2017
+ }
2018
+ ?>
2019
+ "> <?php esc_html_e( 'Abandoned Orders', 'woocommerce-abandoned-cart' ); ?> </a>
2020
+ <a href="admin.php?page=woocommerce_ac_page&action=emailtemplates" class="nav-tab
2021
+ <?php
2022
+ if ( isset( $active_emailtemplates ) ) {
2023
+ echo esc_attr( $active_emailtemplates );
2024
+ }
2025
+ ?>
2026
+ "> <?php esc_html_e( 'Email Templates', 'woocommerce-abandoned-cart' ); ?> </a>
2027
+ <a href="admin.php?page=woocommerce_ac_page&action=emailsettings" class="nav-tab
2028
+ <?php
2029
+ if ( isset( $active_settings ) ) {
2030
+ echo esc_attr( $active_settings );
2031
+ }
2032
+ ?>
2033
+ "> <?php esc_html_e( 'Settings', 'woocommerce-abandoned-cart' ); ?> </a>
2034
+ <a href="admin.php?page=woocommerce_ac_page&action=stats" class="nav-tab
2035
+ <?php
2036
+ if ( isset( $active_stats ) ) {
2037
+ echo esc_attr( $active_stats );
2038
+ }
2039
+ ?>
2040
+ "> <?php esc_html_e( 'Recovered Orders', 'woocommerce-abandoned-cart' ); ?> </a>
2041
+ <a href="admin.php?page=woocommerce_ac_page&action=report" class="nav-tab
2042
+ <?php
2043
+ if ( isset( $active_report ) ) {
2044
+ echo esc_attr( $active_report );
2045
+ }
2046
+ ?>
2047
+ "> <?php esc_html_e( 'Product Report', 'woocommerce-abandoned-cart' ); ?> </a>
2048
 
2049
  <?php do_action( 'wcal_add_settings_tab' ); ?>
2050
  </h2>
2053
 
2054
  /**
2055
  * It will add the scripts needed for the plugin.
2056
+ *
2057
  * @hook admin_enqueue_scripts
2058
+ * @param string $hook Name of hook.
2059
  * @since 1.0
2060
  */
2061
+ public function wcal_enqueue_scripts_js( $hook ) {
2062
  global $pagenow, $woocommerce;
2063
+ $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2064
+ $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2065
 
2066
+ if ( '' === $page || 'woocommerce_ac_page' !== $page ) {
2067
  return;
2068
  } else {
2069
  wp_enqueue_script( 'jquery' );
2070
+ wp_enqueue_script( 'jquery-ui-core' );
2071
+
2072
+ wp_enqueue_script( 'jquery-ui-datepicker' );
2073
  wp_enqueue_script(
2074
+ 'jquery-tip',
2075
+ plugins_url( '/assets/js/jquery.tipTip.minified.js', __FILE__ ),
 
2076
  '',
2077
+ WCAL_PLUGIN_VERSION,
2078
  false
2079
  );
2080
+ $mode = isset( $_GET['mode'] ) ? sanitize_text_field( wp_unslash( $_GET['mode'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2081
+ if ( 'emailtemplates' === $action && ( 'addnewtemplate' === $mode || 'edittemplate' === $mode ) ) {
2082
+ wp_register_script( 'woocommerce_admin', WC()->plugin_url() . '/assets/js/admin/woocommerce_admin.min.js', array( 'jquery', 'jquery-tiptip' ), WCAL_PLUGIN_VERSION, false );
 
 
 
 
 
 
 
 
 
 
2083
  wp_enqueue_script( 'woocommerce_admin');
2084
  $locale = localeconv();
2085
  $decimal = isset( $locale['decimal_point'] ) ? $locale['decimal_point'] : '.';
2086
  $params = array(
2087
+ // translators: %s: decimal.
2088
  'i18n_decimal_error' => sprintf( __( 'Please enter in decimal (%s) format without thousand separators.', 'woocommerce' ), $decimal ),
2089
+ // translators: %s: price decimal separator.
2090
  'i18n_mon_decimal_error' => sprintf( __( 'Please enter in monetary decimal (%s) format without thousand separators and currency symbols.', 'woocommerce' ), wc_get_price_decimal_separator() ),
2091
  'i18n_country_iso_error' => __( 'Please enter in country code with two capital letters.', 'woocommerce' ),
2092
  'i18_sale_less_than_regular_error' => __( 'Please enter in a value less than the regular price.', 'woocommerce' ),
2101
  'export_products' => esc_url_raw( admin_url( 'edit.php?post_type=product&page=product_exporter' ) ),
2102
  ),
2103
  );
2104
+
2105
+ // If we dont localize this script then from the WooCommerce check it will not run the javascript further and tooltip wont show any data.
2106
+ // Also, we need above all parameters for the WooCoomerce js file. So we have taken it from the WooCommerce. @since: 5.1.2
 
 
2107
  wp_localize_script( 'woocommerce_admin', 'woocommerce_admin', $params );
2108
+ }
2109
  ?>
2110
  <script type="text/javascript" >
2111
  function wcal_activate_email_template( template_id, active_state ) {
2113
  }
2114
  </script>
2115
  <?php
2116
+ $js_src = includes_url( 'js/tinymce/' ) . 'tinymce.min.js';
2117
+ wp_enqueue_script( 'tinyMce_ac', $js_src, '', WCAL_PLUGIN_VERSION, false );
2118
+ wp_enqueue_script(
2119
+ 'ac_email_variables',
2120
+ plugins_url( '/assets/js/abandoncart_plugin_button.js', __FILE__ ),
2121
+ '',
2122
+ WCAL_PLUGIN_VERSION,
2123
+ false
2124
+ );
2125
+ wp_enqueue_script(
2126
+ 'wcal_activate_template',
2127
+ plugins_url( '/assets/js/wcal_template_activate.js', __FILE__ ),
2128
+ '',
2129
+ WCAL_PLUGIN_VERSION,
2130
+ false
2131
+ );
2132
+
2133
+ // Needed only on the dashboard page.
2134
+ if ( 'woocommerce_ac_page' === $page && ( '' === $action || 'dashboard' === $action ) ) {
2135
+ wp_register_script( 'jquery-ui-datepicker', WC()->plugin_url() . '/assets/js/admin/ui-datepicker.js', '', WCAL_PLUGIN_VERSION, false );
2136
  wp_enqueue_script( 'jquery-ui-datepicker' );
2137
 
2138
+ wp_enqueue_script(
2139
+ 'bootstrap_js',
2140
+ plugins_url( '/assets/js/admin/bootstrap.min.js', __FILE__ ),
2141
+ '',
2142
+ WCAL_PLUGIN_VERSION,
2143
+ false
2144
+ );
2145
 
2146
+ wp_enqueue_script(
2147
  'reports_js',
2148
+ plugins_url( '/assets/js/admin/wcal_adv_dashboard.min.js', __FILE__ ),
 
2149
  '',
2150
+ WCAL_PLUGIN_VERSION,
2151
  false
2152
  );
2153
  }
2154
+ // Needed only on the abandoned orders page.
2155
+ wp_enqueue_script(
2156
+ 'wcal_abandoned_cart_details',
2157
+ plugins_url( '/assets/js/admin/wcal_abandoned_cart_detail_modal.min.js', __FILE__ ),
2158
+ '',
2159
+ WCAL_PLUGIN_VERSION,
2160
+ false
2161
+ );
2162
 
2163
+ wp_enqueue_script(
2164
+ 'wcal_admin_notices',
2165
+ plugins_url( '/assets/js/admin/wcal_ts_dismiss_notice.js', __FILE__ ),
2166
+ '',
2167
+ WCAL_PLUGIN_VERSION,
2168
+ false
2169
+ );
2170
+ wp_localize_script(
2171
+ 'wcal_admin_notices',
2172
+ 'wcal_dismiss_params',
2173
+ array(
2174
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
2175
  )
2176
  );
2177
  }
2179
 
2180
  /**
2181
  * It will add the parameter to the editor.
2182
+ *
2183
  * @hook tiny_mce_before_init
2184
+ * @param array $in - Editor params.
2185
+ * @return array $in - Editor params.
2186
  * @since 2.6
2187
  */
2188
+ public function wcal_format_tiny_mce( $in ) {
2189
  $in['force_root_block'] = false;
2190
  $in['valid_children'] = '+body[style]';
2191
  $in['remove_linebreaks'] = false;
2202
  $in['wpautop'] = false;
2203
  $in['apply_source_formatting'] = true;
2204
  $in['cleanup'] = true;
2205
+ $in['convert_newlines_to_brs'] = false;
2206
  $in['fullpage_default_xml_pi'] = false;
2207
  $in['convert_urls'] = false;
2208
+ // Do not remove redundant BR tags.
2209
+ $in['remove_redundant_brs'] = false;
2210
  return $in;
2211
  }
2212
 
2213
  /**
2214
  * It will add the necesaary css for the plugin.
2215
+ *
2216
  * @hook admin_enqueue_scripts
2217
+ * @param string $hook Name of page.
2218
  * @since 1.0
2219
  */
2220
+ public function wcal_enqueue_scripts_css( $hook ) {
2221
 
2222
  global $pagenow;
2223
 
2224
+ $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2225
+ $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2226
 
2227
+ if ( 'woocommerce_ac_page' !== $page ) {
2228
  return;
2229
+ } elseif ( 'woocommerce_ac_page' === $page && ( 'dashboard' === $action || '' === $action ) ) {
2230
+ wp_enqueue_style( 'wcal-dashboard-adv', plugins_url( '/assets/css/admin/wcal_reports_adv.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2231
 
2232
+ wp_register_style( 'bootstrap_css', plugins_url( '/assets/css/admin/bootstrap.min.css', __FILE__ ), '', WCAL_PLUGIN_VERSION, 'all' );
2233
  wp_enqueue_style( 'bootstrap_css' );
2234
 
2235
+ wp_enqueue_style( 'wcal-font-awesome', plugins_url( '/assets/css/admin/font-awesome.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2236
+
2237
+ wp_enqueue_style( 'wcal-font-awesome-min', plugins_url( '/assets/css/admin/font-awesome.min.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2238
+
2239
+ wp_enqueue_style( 'jquery-ui', plugins_url( '/assets/css/admin/jquery-ui.css', __FILE__ ), '', WCAL_PLUGIN_VERSION, false );
2240
+ wp_enqueue_style( 'woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css', '', WCAL_PLUGIN_VERSION );
2241
+ wp_enqueue_style( 'jquery-ui-style', plugins_url( '/assets/css/admin/jquery-ui-smoothness.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2242
+ wp_enqueue_style( 'wcal-reports', plugins_url( '/assets/css/admin/wcal_reports.min.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2243
 
2244
+ } elseif ( 'woocommerce_ac_page' === $page ) {
 
 
 
 
 
2245
 
2246
+ wp_enqueue_style( 'jquery-ui', plugins_url( '/assets/css/admin/jquery-ui.css', __FILE__ ), '', WCAL_PLUGIN_VERSION, false );
2247
+ wp_enqueue_style( 'woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css', '', WCAL_PLUGIN_VERSION );
2248
 
2249
+ wp_enqueue_style( 'jquery-ui-style', plugins_url( '/assets/css/admin/jquery-ui-smoothness.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2250
+ wp_enqueue_style( 'abandoned-orders-list', plugins_url( '/assets/css/view.abandoned.orders.style.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2251
+ wp_enqueue_style( 'wcal_email_template', plugins_url( '/assets/css/wcal_template_activate.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2252
+ wp_enqueue_style( 'wcal_cart_details', plugins_url( '/assets/css/admin/wcal_abandoned_cart_detail_modal.min.css', __FILE__ ), '', WCAL_PLUGIN_VERSION );
2253
  }
2254
  }
2255
 
 
2256
  /**
2257
  * When we have added the wp list table for the listing then while deleting the record with the bulk action it was showing
2258
  * the notice. To overcome the wp redirect warning we need to start the ob_start.
2259
+ *
2260
  * @hook init
2261
  * @since 2.5.2
2262
  */
2263
+ public function wcal_app_output_buffer() {
2264
  ob_start();
2265
  }
2266
 
2269
  * It will also update the template records and display the template fields.
2270
  * It will also show the abandoned cart details page.
2271
  * It will also show the details of all the tabs.
2272
+ *
2273
  * @globals mixed $wpdb
2274
  * @since 1.0
2275
  */
2276
+ public function wcal_menu_page() {
2277
 
2278
  if ( is_user_logged_in() ) {
2279
  global $wpdb;
2280
+ // Check the user capabilities.
2281
  if ( ! current_user_can( 'manage_woocommerce' ) ) {
2282
+ wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'woocommerce-abandoned-cart' ) );
2283
  }
2284
  ?>
2285
  <div class="wrap">
2286
+ <h2><?php esc_html_e( 'WooCommerce - Abandon Cart Lite', 'woocommerce-abandoned-cart' ); ?></h2>
2287
  <?php
2288
 
2289
+ if ( isset( $_GET['ac_update'] ) && 'email_templates' === sanitize_text_field( wp_unslash( $_GET['ac_update'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
2290
  $status = wcal_common::update_templates_table();
2291
 
2292
+ if ( false !== $status ) {
2293
  wcal_common::show_update_success();
2294
  } else {
2295
  wcal_common::show_update_failure();
2297
  }
2298
 
2299
  if ( isset( $_GET['action'] ) ) {
2300
+ $action = sanitize_text_field( wp_unslash( $_GET['action'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
2301
  } else {
2302
+ $action = '';
2303
  $action = apply_filters( 'wcal_default_tab', $action );
2304
  }
2305
+ $mode = isset( $_GET['mode'] ) ? sanitize_text_field( wp_unslash( $_GET['mode'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
 
 
 
 
2306
  $this->wcal_display_tabs();
2307
 
2308
+ do_action( 'wcal_add_tab_content' );
2309
+
2310
+ // When we delete the item from the below drop down it is registred in action 2.
2311
+ $action_two = isset( $_GET['action2'] ) ? sanitize_text_field( wp_unslash( $_GET['action2'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2312
 
 
 
 
 
 
 
 
 
2313
  // Detect when a bulk action is being triggered on abandoned orders page.
2314
  if ( 'wcal_delete' === $action || 'wcal_delete' === $action_two ) {
2315
  $ids = isset( $_GET['abandoned_order_id'] ) && is_array( $_GET['abandoned_order_id'] ) ? array_map( 'intval', wp_unslash( $_GET['abandoned_order_id'] ) ) : sanitize_text_field( wp_unslash( $_GET['abandoned_order_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
2344
 
2345
  // Detect when a bulk action is being triggered on templates page.
2346
  if ( 'wcal_delete_template' === $action || 'wcal_delete_template' === $action_two ) {
2347
+ $ids = isset( $_GET['template_id'] ) && is_array( $_GET['template_id'] ) ? array_map( 'intval', wp_unslash( $_GET['template_id'] ) ) : sanitize_text_field( wp_unslash( $_GET['template_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
2348
  if ( ! is_array( $ids ) ) {
2349
  $ids = array( $ids );
2350
  }
2376
  <div id="message" class="updated fade">
2377
  <p><strong><?php esc_html_e( 'The Template has been successfully deleted.', 'woocommerce-abandoned-cart' ); ?></strong></p>
2378
  </div>
2379
+ <?php
2380
+ }
2381
+ if ( 'emailsettings' === $action ) {
2382
+ // Save the field values.
2383
  ?>
2384
+ <p><?php esc_html_e( 'Change settings for sending email notifications to Customers, to Admin etc.', 'woocommerce-abandoned-cart' ); ?></p>
2385
  <div id="content">
2386
  <?php
2387
+ $wcal_general_settings_class = '';
2388
+ $wcal_email_setting = '';
2389
+ $wcap_sms_settings = '';
2390
+ $wcap_atc_settings = '';
2391
+ $wcap_fb_settings = '';
2392
+
2393
+ $section = isset( $_GET['wcal_section'] ) ? sanitize_text_field( wp_unslash( $_GET['wcal_section'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2394
+ switch ( $section ) {
2395
+ case 'wcal_general_settings':
2396
+ case '':
2397
+ $wcal_general_settings_class = 'current';
2398
+ break;
2399
+ case 'wcal_email_settings':
2400
+ $wcal_email_setting = 'current';
2401
+ break;
2402
+ case 'wcap_sms_settings':
2403
+ $wcap_sms_settings = 'current';
2404
+ break;
2405
+ case 'wcap_atc_settings':
2406
+ $wcap_atc_settings = 'current';
2407
+ break;
2408
+ case 'wcap_fb_settings':
2409
+ $wcap_fb_settings = 'current';
2410
+ break;
2411
+ default:
2412
+ $wcal_general_settings_class = 'current';
2413
+ break;
2414
+ }
2415
+ ?>
 
 
 
 
2416
  <ul class="subsubsub" id="wcal_general_settings_list">
2417
  <li>
2418
+ <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcal_general_settings" class="<?php echo esc_attr( $wcal_general_settings_class ); ?>"><?php esc_html_e( 'General Settings', 'woocommerce-abandoned-cart' ); ?> </a> |
2419
  </li>
2420
+ <li>
2421
+ <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcal_email_settings" class="<?php echo esc_attr( $wcal_email_setting ); ?>"><?php esc_html_e( 'Email Sending Settings', 'woocommerce-abandoned-cart' ); ?> </a> |
2422
  </li>
2423
  <li>
2424
+ <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_atc_settings" class="<?php echo esc_attr( $wcap_atc_settings ); ?>"><?php esc_html_e( 'Add To Cart Popup Editor', 'woocommerce-ac' ); ?> </a> |
2425
  </li>
2426
  <li>
2427
+ <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_fb_settings" class="<?php echo esc_attr( $wcap_fb_settings ); ?>"><?php esc_html_e( 'Facebook Messenger', 'woocommerce-ac' ); ?> </a> |
2428
  </li>
2429
  <li>
2430
+ <a href="admin.php?page=woocommerce_ac_page&action=emailsettings&wcal_section=wcap_sms_settings" class="<?php echo esc_attr( $wcap_sms_settings ); ?>"><?php esc_html_e( 'SMS', 'woocommerce-ac' ); ?> </a>
2431
  </li>
 
2432
  </ul>
2433
  <br class="clear">
2434
+ <?php
2435
+ if ( 'wcal_general_settings' === $section || '' === $section ) {
2436
+ ?>
2437
  <form method="post" action="options.php">
2438
  <?php settings_fields( 'woocommerce_ac_settings' ); ?>
2439
  <?php do_settings_sections( 'woocommerce_ac_page' ); ?>
2440
  <?php settings_errors(); ?>
2441
  <?php submit_button(); ?>
2442
  </form>
2443
+ <?php
2444
+ } elseif ( 'wcal_email_settings' === $section ) {
2445
+ ?>
2446
  <form method="post" action="options.php">
2447
+ <?php settings_fields( 'woocommerce_ac_email_settings' ); ?>
2448
  <?php do_settings_sections( 'woocommerce_ac_email_page' ); ?>
2449
  <?php settings_errors(); ?>
2450
  <?php submit_button(); ?>
2451
  </form>
2452
+ <?php
2453
+ } elseif ( 'wcap_atc_settings' === $section ) {
2454
  WCAP_Pro_Settings::wcap_atc_settings();
2455
+ } elseif ( 'wcap_fb_settings' === $section ) {
2456
  WCAP_Pro_Settings::wcap_fb_settings();
2457
+ } elseif ( 'wcap_sms_settings' === $section ) {
2458
  WCAP_Pro_Settings::wcap_sms_settings();
2459
  }
2460
  ?>
2461
  </div>
2462
+ <?php
2463
+ } elseif ( 'dashboard' === $action || '' === $action || '-1' === $action || '1' === $action_two ) {
2464
+ include_once 'includes/classes/class-wcal-dashboard-report.php';
2465
+ Wcal_Dashboard_Report::wcal_dashboard_display();
2466
 
2467
+ } elseif ( 'listcart' === $action ) {
2468
+
2469
+ ?>
2470
+ <p> <?php esc_html_e( 'The list below shows all Abandoned Carts which have remained in cart for a time higher than the "Cart abandoned cut-off time" setting.', 'woocommerce-abandoned-cart' ); ?> </p>
2471
  <?php
2472
  $get_all_abandoned_count = wcal_common::wcal_get_abandoned_order_count( 'wcal_all_abandoned' );
2473
  $get_registered_user_ac_count = wcal_common::wcal_get_abandoned_order_count( 'wcal_all_registered' );
2482
  if ( $get_guest_user_ac_count > 1 ) {
2483
  $wcal_user_gus_text = 'Users';
2484
  }
2485
+ $wcal_all_abandoned_carts = '';
2486
+ $section = '';
2487
+ $wcal_all_registered = '';
2488
+ $wcal_all_guest = '';
2489
+ $wcal_all_visitor = '';
2490
+
2491
+ $section = isset( $_GET['wcal_section'] ) ? sanitize_text_field( wp_unslash( $_GET['wcal_section'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2492
+ if ( 'wcal_all_abandoned' === $section || '' === $section ) {
2493
+ $wcal_all_abandoned_carts = 'current';
2494
  }
2495
 
2496
+ if ( 'wcal_all_registered' === $section ) {
2497
+ $wcal_all_registered = 'current';
2498
+ $wcal_all_abandoned_carts = '';
2499
  }
2500
+ if ( 'wcal_all_guest' === $section ) {
2501
+ $wcal_all_guest = 'current';
2502
+ $wcal_all_abandoned_carts = '';
2503
  }
2504
 
2505
+ if ( 'wcal_all_visitor' === $section ) {
2506
+ $wcal_all_visitor = 'current';
2507
+ $wcal_all_abandoned_carts = '';
2508
  }
2509
  ?>
2510
  <ul class="subsubsub" id="wcal_recovered_orders_list">
2511
  <li>
2512
+ <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_abandoned" class="<?php echo esc_attr( $wcal_all_abandoned_carts ); ?>"><?php esc_html_e( 'All ', 'woocommerce-abandoned-cart' ); ?> <span class = "count" > <?php echo esc_html( "( $get_all_abandoned_count )" ); ?> </span></a>
2513
  </li>
2514
 
2515
+ <?php if ( $get_registered_user_ac_count > 0 ) { ?>
2516
+ <li><?php // translators: Users. ?>
2517
+ | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_registered" class="<?php echo esc_attr( $wcal_all_registered ); ?>"><?php printf( esc_html__( 'Registered %s', 'woocommerce-abandoned-cart' ), esc_html( $wcal_user_reg_text ) ); ?> <span class = "count" > <?php echo esc_html( "( $get_registered_user_ac_count )" ); ?> </span></a>
2518
  </li>
2519
  <?php } ?>
2520
 
2521
+ <?php if ( $get_guest_user_ac_count > 0 ) { ?>
2522
+ <li><?php // translators: Users. ?>
2523
+ | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_guest" class="<?php echo esc_attr( $wcal_all_guest ); ?>"><?php printf( esc_html__( 'Guest %s', 'woocommerce-abandoned-cart' ), esc_html( $wcal_user_gus_text ) ); ?> <span class = "count" > <?php echo esc_html( "( $get_guest_user_ac_count )" ); ?> </span></a>
2524
  </li>
2525
  <?php } ?>
2526
 
2527
+ <?php if ( $get_visitor_user_ac_count > 0 ) { ?>
2528
  <li>
2529
+ | <a href="admin.php?page=woocommerce_ac_page&action=listcart&wcal_section=wcal_all_visitor" class="<?php echo esc_attr( $wcal_all_visitor ); ?>"><?php esc_html_e( 'Carts without Customer Details', 'woocommerce-abandoned-cart' ); ?> <span class = "count" > <?php echo esc_html( "( $get_visitor_user_ac_count )" ); ?> </span></a>
2530
  </li>
2531
  <?php } ?>
2532
  </ul>
2533
 
2534
  <?php
2535
  global $wpdb;
2536
+ include_once 'includes/classes/class-wcal-abandoned-orders-table.php';
2537
  $wcal_abandoned_order_list = new WCAL_Abandoned_Orders_Table();
2538
  $wcal_abandoned_order_list->wcal_abandoned_order_prepare_items();
2539
  ?>
2540
  <div class="wrap">
2541
  <form id="wcal-abandoned-orders" method="get" >
2542
  <input type="hidden" name="page" value="woocommerce_ac_page" />
2543
+ <input type="hidden" name="action" value="listcart" />
2544
+ <?php $wcal_abandoned_order_list->display(); ?>
2545
  </form>
2546
  </div>
2547
  <?php
2548
+ } elseif ( ( 'emailtemplates' === $action && ( 'edittemplate' !== $mode && 'addnewtemplate' !== $mode ) || '' === $action || '-1' === $action || '-1' === $action_two ) ) {
2549
+ ?>
2550
+ <p> <?php esc_html_e( 'Add email templates at different intervals to maximize the possibility of recovering your abandoned carts.', 'woocommerce-abandoned-cart' ); ?> </p>
2551
+ <?php
2552
+ // Save the field values.
2553
+ $insert_template_successfuly = '';
2554
+ $update_template_successfuly = '';
2555
+ $woocommerce_ac_email_subject = isset( $_POST['woocommerce_ac_email_subject'] ) ? trim( htmlspecialchars( sanitize_text_field( wp_unslash( $_POST['woocommerce_ac_email_subject'] ) ) ), ENT_QUOTES ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2556
+ $woocommerce_ac_email_body = isset( $_POST['woocommerce_ac_email_body'] ) ? trim( wp_unslash( $_POST['woocommerce_ac_email_body'] ) ) : ''; // phpcs:ignore
2557
+ $woocommerce_ac_template_name = isset( $_POST['woocommerce_ac_template_name'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['woocommerce_ac_template_name'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2558
+ $woocommerce_ac_email_header = isset( $_POST['wcal_wc_email_header'] ) ? stripslashes( trim( htmlspecialchars( sanitize_text_field( wp_unslash( $_POST['wcal_wc_email_header'] ) ) ), ENT_QUOTES ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2559
+
2560
+ $email_frequency = isset( $_POST['email_frequency'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['email_frequency'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2561
+ $day_or_hour = isset( $_POST['day_or_hour'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['day_or_hour'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2562
+ $is_wc_template = empty( $_POST['is_wc_template'] ) ? '0' : '1'; // phpcs:ignore WordPress.Security.NonceVerification
2563
+
2564
+ if ( isset( $_POST['ac_settings_frm'] ) && 'save' === sanitize_text_field( wp_unslash( $_POST['ac_settings_frm'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
2565
+ $default_value = 0;
2566
+
2567
+ $insert_template_successfuly = $wpdb->query( //phpcs:ignore
2568
+ $wpdb->prepare(
2569
+ 'INSERT INTO `' . $wpdb->prefix . 'ac_email_templates_lite` (subject, body, frequency, day_or_hour, template_name, is_wc_template, default_template, wc_email_header ) VALUES ( %s, %s, %d, %s, %s, %s, %d, %s )',
2570
+ $woocommerce_ac_email_subject,
2571
+ $woocommerce_ac_email_body,
2572
+ $email_frequency,
2573
+ $day_or_hour,
2574
+ $woocommerce_ac_template_name,
2575
+ $is_wc_template,
2576
+ $default_value,
2577
+ $woocommerce_ac_email_header
2578
+ )
2579
+ );
2580
+ }
 
 
 
2581
 
2582
+ if ( isset( $_POST['ac_settings_frm'] ) && 'update' === sanitize_text_field( wp_unslash( $_POST['ac_settings_frm'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
 
 
2583
 
2584
+ $updated_is_active = '0';
2585
+ $id = isset( $_POST['id'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['id'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
 
 
 
2586
 
2587
+ $check_results = $wpdb->get_results( //phpcs:ignore
2588
+ $wpdb->prepare(
2589
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_email_templates_lite` WHERE id = %d',
2590
+ $id
2591
+ )
2592
+ );
2593
+ $default_value = '';
2594
 
2595
+ if ( count( $check_results ) > 0 ) {
2596
+ if ( isset( $check_results[0]->default_template ) && '1' === $check_results[0]->default_template ) {
2597
+ $default_value = '1';
 
2598
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2599
  }
2600
 
2601
+ $update_template_successfuly = $wpdb->query( //phpcs:ignore
2602
+ $wpdb->prepare(
2603
+ 'UPDATE `' . $wpdb->prefix . 'ac_email_templates_lite` SET subject = %s, body = %s, frequency = %d, day_or_hour = %s, template_name = %s, is_wc_template = %s, default_template = %d, wc_email_header = %s WHERE id = %d',
2604
+ $woocommerce_ac_email_subject,
2605
+ $woocommerce_ac_email_body,
2606
+ $email_frequency,
2607
+ $day_or_hour,
2608
+ $woocommerce_ac_template_name,
2609
+ $is_wc_template,
2610
+ $default_value,
2611
+ $woocommerce_ac_email_header,
2612
+ $id
2613
+ )
2614
+ );
2615
+ }
2616
 
2617
+ if ( 'emailtemplates' === $action && 'removetemplate' === $mode ) {
2618
+ $id_remove = isset( $_GET['id'] ) ? sanitize_text_field( wp_unslash( $_GET['id'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2619
+ $wpdb->query( //phpcs:ignore
2620
+ $wpdb->prepare(
2621
+ 'DELETE FROM `' . $wpdb->prefix . 'ac_email_templates_lite` WHERE id= %d ',
2622
+ $id_remove
2623
+ )
2624
+ );
2625
+ }
2626
 
2627
+ if ( 'emailtemplates' === $action && 'activate_template' === $mode ) {
2628
+ $template_id = isset( $_GET['id'] ) ? sanitize_text_field( wp_unslash( $_GET['id'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2629
+ $current_template_status = isset( $_GET['active_state'] ) ? sanitize_text_field( wp_unslash( $_GET['active_state'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2630
 
2631
+ if ( '1' === $current_template_status ) {
2632
+ $active = '0';
2633
+ } else {
2634
+ $active = '1';
2635
+ $get_selected_template_result = $wpdb->get_results( // phpcs:ignore
2636
+ $wpdb->prepare(
2637
+ 'SELECT * FROM `' . $wpdb->prefix . 'ac_email_templates_lite` WHERE id = %d',
2638
+ $template_id
2639
+ )
2640
+ );
2641
 
2642
+ $email_frequncy = $get_selected_template_result[0]->frequency;
2643
+ $email_day_or_hour = $get_selected_template_result[0]->day_or_hour;
2644
+ $wcap_updated = $wpdb->query( // phpcs:ignore
2645
+ $wpdb->prepare(
2646
+ 'UPDATE `' . $wpdb->prefix . 'ac_email_templates_lite` SET is_active = %s WHERE frequency = %s AND day_or_hour = %s',
2647
+ 0,
2648
+ $email_frequncy,
2649
+ $email_day_or_hour
2650
+ )
2651
+ );
2652
  }
2653
 
2654
+ $wpdb->query( // phpcs:ignore
2655
+ $wpdb->prepare(
2656
+ 'UPDATE `' . $wpdb->prefix . 'ac_email_templates_lite` SET is_active = %s WHERE id = %s',
2657
+ $active,
2658
+ $template_id
2659
+ )
2660
+ );
 
 
 
 
 
 
 
 
 
 
 
 
2661
 
2662
+ wp_safe_redirect( admin_url( '/admin.php?page=woocommerce_ac_page&action=emailtemplates' ) );
2663
+ }
2664
+
2665
+ if ( isset( $_POST['ac_settings_frm'] ) && 'save' === $_POST['ac_settings_frm'] && ( isset( $insert_template_successfuly ) && '' !== $insert_template_successfuly ) ) { // phpcs:ignore WordPress.Security.NonceVerification
2666
+ ?>
2667
+ <div id="message" class="updated fade">
2668
+ <p>
2669
+ <strong>
2670
+ <?php esc_html_e( 'The Email Template has been successfully added. In order to start sending this email to your customers, please activate it.', 'woocommerce-abandoned-cart' ); ?>
2671
+ </strong>
2672
+ </p>
2673
+ </div>
2674
+ <?php
2675
+ } elseif ( isset( $_POST['ac_settings_frm'] ) && 'save' === $_POST['ac_settings_frm'] && ( isset( $insert_template_successfuly ) && '' === $insert_template_successfuly ) ) { // phpcs:ignore WordPress.Security.NonceVerification
 
 
 
 
 
2676
  ?>
2677
+ <div id="message" class="error fade">
2678
+ <p>
2679
+ <strong>
2680
+ <?php esc_html_e( 'There was a problem adding the email template. Please contact the plugin author via <a href= "https://wordpress.org/support/plugin/woocommerce-abandoned-cart">support forum</a>.', 'woocommerce-abandoned-cart' ); ?>
2681
+ </strong>
2682
  </p>
2683
+ </div>
2684
+ <?php
2685
+ }
2686
 
2687
+ if ( isset( $_POST['ac_settings_frm'] ) && 'update' === $_POST['ac_settings_frm'] && isset( $update_template_successfuly ) && false !== $update_template_successfuly ) { // phpcs:ignore WordPress.Security.NonceVerification
2688
+ ?>
2689
+ <div id="message" class="updated fade">
2690
+ <p>
2691
+ <strong>
2692
+ <?php esc_html_e( 'The Email Template has been successfully updated.', 'woocommerce-abandoned-cart' ); ?>
2693
+ </strong>
2694
+ </p>
 
 
 
 
 
2695
  </div>
2696
  <?php
2697
+ } elseif ( isset( $_POST['ac_settings_frm'] ) && 'update' === $_POST['ac_settings_frm'] && isset( $update_template_successfuly ) && false === $update_template_successfuly ) { // phpcs:ignore WordPress.Security.NonceVerification
2698
  ?>
2699
+ <div id="message" class="error fade">
2700
+ <p>
2701
+ <strong>
2702
+ <?php esc_html_e( 'There was a problem updating the email template. Please contact the plugin author via <a href= "https://wordpress.org/support/plugin/woocommerce-abandoned-cart">support forum</a>.', 'woocommerce-abandoned-cart' ); ?>
2703
+ </strong>
2704
+ </p>
2705
+ </div>
2706
+ <?php
2707
+ }
2708
+ ?>
2709
+ <div class="tablenav">
2710
+ <p style="float:left;">
2711
+ <a cursor: pointer; href="<?php echo esc_url( 'admin.php?page=woocommerce_ac_page&action=emailtemplates&mode=addnewtemplate' ); ?>" class="button-secondary"><?php esc_html_e( 'Add New Template', 'woocommerce-abandoned-cart' ); ?></a>
2712
+ </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2713
 
2714
+ <?php
2715
+ // From here you can do whatever you want with the data from the $result link.
2716
+ include_once 'includes/classes/class-wcal-templates-table.php';
2717
+ $wcal_template_list = new WCAL_Templates_Table();
2718
+ $wcal_template_list->wcal_templates_prepare_items();
2719
+ ?>
2720
+ <div class="wrap">
2721
+ <form id="wcal-abandoned-templates" method="get" >
2722
+ <input type="hidden" name="page" value="woocommerce_ac_page" />
2723
+ <input type="hidden" name="action" value="emailtemplates" />
2724
+ <?php $wcal_template_list->display(); ?>
2725
+ </form>
2726
+ </div>
2727
+ </div>
2728
+ <?php
2729
+ } elseif ( 'stats' === $action || '' === $action ) {
2730
+ ?>
2731
+ <p>
2732
+ <script language='javascript'>
2733
+ jQuery( document ).ready( function() {
2734
+ jQuery( '#duration_select' ).change( function() {
2735
+ var group_name = jQuery( '#duration_select' ).val();
2736
+ var today = new Date();
2737
+ var start_date = "";
2738
+ var end_date = "";
2739
+ if ( group_name == "yesterday" ) {
2740
+ start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 1 );
2741
+ end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 1 );
2742
+ } else if ( group_name == "today") {
2743
+ start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2744
+ end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2745
+ } else if ( group_name == "last_seven" ) {
2746
+ start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 7 );
2747
+ end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2748
+ } else if ( group_name == "last_fifteen" ) {
2749
+ start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 15 );
2750
+ end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2751
+ } else if ( group_name == "last_thirty" ) {
2752
+ start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 30 );
2753
+ end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2754
+ } else if ( group_name == "last_ninety" ) {
2755
+ start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 90 );
2756
+ end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2757
+ } else if ( group_name == "last_year_days" ) {
2758
+ start_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() - 365 );
2759
+ end_date = new Date( today.getFullYear(), today.getMonth(), today.getDate() );
2760
+ }
2761
 
2762
+ var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
 
2763
 
2764
+ var start_date_value = start_date.getDate() + " " + monthNames[start_date.getMonth()] + " " + start_date.getFullYear();
2765
+ var end_date_value = end_date.getDate() + " " + monthNames[end_date.getMonth()] + " " + end_date.getFullYear();
 
 
 
 
2766
 
2767
+ jQuery( '#start_date' ).val( start_date_value );
2768
+ jQuery( '#end_date' ).val( end_date_value );
2769
+ } );
2770
+ });
2771
+ </script>
2772
+ <?php
2773
+ $duration_range = isset( $_POST['duration_select'] ) ? sanitize_text_field( wp_unslash( $_POST['duration_select'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
2774
+ if ( '' === $duration_range ) {
2775
+ if ( isset( $_GET['duration_select'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
2776
+ $duration_range = sanitize_text_field( wp_unslash( $_GET['duration_select'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
2777
  }
2778
+ }
2779
+ if ( '' === $duration_range ) {
2780
+ $duration_range = 'last_seven';
2781
+ }
2782
 
2783
+ echo esc_html_e( 'The Report below shows how many Abandoned Carts we were able to recover for you by sending automatic emails to encourage shoppers.', 'woocommerce-abandoned-cart' );
2784
+ ?>
2785
+ <div id="recovered_stats" class="postbox" style="display:block">
2786
+ <div class="inside">
2787
+ <form method="post" action="admin.php?page=woocommerce_ac_page&action=stats" id="ac_stats">
2788
+ <select id="duration_select" name="duration_select" >
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2789
  <?php
2790
+ foreach ( $this->duration_range_select as $key => $value ) {
2791
+ $sel = '';
2792
+ if ( $key == $duration_range ) { // phpcs:ignore
2793
+ $sel = ' selected ';
2794
+ }
2795
+ printf(
2796
+ '<option value="%s" %s> %s </option>',
2797
+ esc_attr( $key ),
2798
+ esc_attr( $sel ),
2799
+ esc_attr( $value )
2800
+ );
2801
+ }
2802
+ $date_sett = $this->start_end_dates[ $duration_range ];
2803
+ ?>
2804
+ </select>
2805
+ <script type="text/javascript">
2806
+ jQuery( document ).ready( function() {
2807
+ var formats = ["d.m.y", "d M yy","MM d, yy"];
2808
+ jQuery( "#start_date" ).datepicker( { dateFormat: formats[1] } );
2809
+ });
2810
+
2811
+ jQuery( document ).ready( function()
2812
+ {
2813
+ var formats = ["d.m.y", "d M yy","MM d, yy"];
2814
+ jQuery( "#end_date" ).datepicker( { dateFormat: formats[1] } );
2815
+ });
2816
+ </script>
2817
+ <?php
2818
+ include_once 'includes/classes/class-wcal-recover-orders-table.php';
2819
+ $wcal_recover_orders_list = new WCAL_Recover_Orders_Table();
2820
+ $wcal_recover_orders_list->wcal_recovered_orders_prepare_items();
2821
 
2822
+ $start_date_range = isset( $_POST['start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['start_date'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification
 
2823
 
2824
+ if ( '' === $start_date_range ) {
2825
+ $start_date_range = $date_sett['start_date'];
2826
+ }
2827
 
2828
+ $end_date_range = isset( $_POST['end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['end_date'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification
 
2829
 
2830
+ if ( '' === $end_date_range ) {
2831
+ $end_date_range = $date_sett['end_dat