woocommerce-smart-coupons

This commit is contained in:
Tony Volpe
2024-06-17 16:29:48 -04:00
parent c52ceefa4b
commit 39e0717541
237 changed files with 79624 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
Copyright (c) 2013 Trent Richardson
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,427 @@
/* Coupons By Location styles */
span.search label{
font-size: 1em !important;
float:left !important;
}
label.billing{
width: 75px !important;
margin-left: 1px !important;
}
label.shipping{
margin-left: 0px !important;
}
.chosen-container-multi .chosen-choices .search-field input{
height: 21px !important;
}
/*==============================
CHOSEN CSS - Added from woo 2.6
================================*/
.chosen-container {
position: relative;
display: inline-block;
vertical-align: middle;
font-size: 13px;
zoom: 1;
user-select: none
}
.chosen-container .chosen-drop {
position: absolute;
top: 100%;
left: -9999px;
z-index: 1010;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
border: 1px solid #aaa;
border-top: 0;
background: #fff;
box-shadow: 0 4px 5px rgba(0, 0, 0, .15)
}
.chosen-container.chosen-with-drop .chosen-drop {
left: 0
}
.chosen-container a {
cursor: pointer
}
.chosen-container-single .chosen-single {
position: relative;
display: block;
overflow: hidden;
padding: 0 0 0 8px;
height: 26px;
border: 1px solid #aaa;
border-radius: 5px;
background-color: #fff;
background: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(20%, #fff), color-stop(50%, #f6f6f6), color-stop(52%, #eee), color-stop(100%, #f4f4f4));
background: -webkit-linear-gradient(top, #fff 20%, #f6f6f6 50%, #eee 52%, #f4f4f4 100%);
background: -moz-linear-gradient(top, #fff 20%, #f6f6f6 50%, #eee 52%, #f4f4f4 100%);
background: -o-linear-gradient(top, #fff 20%, #f6f6f6 50%, #eee 52%, #f4f4f4 100%);
background: linear-gradient(top, #fff 20%, #f6f6f6 50%, #eee 52%, #f4f4f4 100%);
background-clip: padding-box;
box-shadow: 0 0 3px #fff inset, 0 1px 1px rgba(0, 0, 0, .1);
color: #444;
text-decoration: none;
white-space: nowrap;
line-height: 26px
}
.chosen-container-single .chosen-default {
color: #999
}
.chosen-container-single .chosen-single span {
display: block;
overflow: hidden;
margin-right: 26px;
text-overflow: ellipsis;
white-space: nowrap
}
.chosen-container-single .chosen-single-with-deselect span {
margin-right: 38px
}
.chosen-container-single .chosen-single abbr {
position: absolute;
top: 6px;
right: 26px;
display: block;
width: 12px;
height: 12px;
background: url(../images/chosen-sprite.png) -42px 1px no-repeat;
font-size: 1px
}
.chosen-container-single .chosen-single abbr:hover,
.chosen-container-single.chosen-disabled .chosen-single abbr:hover {
background-position: -42px -10px
}
.chosen-container-single .chosen-single div {
position: absolute;
top: 0;
right: 0;
display: block;
width: 18px;
height: 100%
}
.chosen-container-single .chosen-single div b {
display: block;
width: 100%;
height: 100%;
background: url(../images/chosen-sprite.png) 0 2px no-repeat
}
.chosen-container-single .chosen-search {
position: relative;
z-index: 1010;
margin: 0;
padding: 3px 4px;
white-space: nowrap
}
.chosen-container-single .chosen-search input[type=text] {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 1px 0;
padding: 4px 20px 4px 5px;
width: 100%;
height: auto;
outline: 0;
border: 1px solid #aaa;
background: url(../images/chosen-sprite.png) 100% -20px no-repeat #fff;
background: url(../images/chosen-sprite.png) 100% -20px no-repeat, -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
background: url(../images/chosen-sprite.png) 100% -20px no-repeat, -webkit-linear-gradient(#eee 1%, #fff 15%);
background: url(../images/chosen-sprite.png) 100% -20px no-repeat, -moz-linear-gradient(#eee 1%, #fff 15%);
background: url(../images/chosen-sprite.png) 100% -20px no-repeat, -o-linear-gradient(#eee 1%, #fff 15%);
background: url(../images/chosen-sprite.png) 100% -20px no-repeat, linear-gradient(#eee 1%, #fff 15%);
font-size: 1em;
font-family: sans-serif;
line-height: normal;
border-radius: 0
}
.chosen-container-single .chosen-drop {
margin-top: -1px;
border-radius: 0 0 4px 4px;
background-clip: padding-box
}
.chosen-container-single.chosen-container-single-nosearch .chosen-search {
position: absolute;
left: -9999px
}
.chosen-container .chosen-results {
position: relative;
overflow-x: hidden;
overflow-y: auto;
margin: 0 4px 4px 0;
padding: 0 0 0 4px;
max-height: 240px;
-webkit-overflow-scrolling: touch
}
.chosen-container .chosen-results li {
display: none;
margin: 0;
padding: 5px 6px;
list-style: none;
line-height: 15px
}
.chosen-container .chosen-results li.active-result {
display: list-item;
cursor: pointer
}
.chosen-container .chosen-results li.disabled-result {
display: list-item;
color: #ccc;
cursor: default
}
.chosen-container .chosen-results li.highlighted {
background-color: #3875d7;
background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);
background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);
background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);
background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
color: #fff
}
.chosen-container .chosen-results li.no-results {
display: list-item;
background: #f4f4f4
}
.chosen-container .chosen-results li.group-result {
display: list-item;
font-weight: 700;
cursor: default
}
.chosen-container .chosen-results li.group-option {
padding-left: 15px
}
.chosen-container .chosen-results li em {
font-style: normal;
text-decoration: underline
}
.chosen-container-multi .chosen-choices {
position: relative;
overflow: hidden;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
width: 100%;
height: auto!important;
height: 1%;
border: 1px solid #aaa;
background-color: #fff;
background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
background-image: -webkit-linear-gradient(#eee 1%, #fff 15%);
background-image: -moz-linear-gradient(#eee 1%, #fff 15%);
background-image: -o-linear-gradient(#eee 1%, #fff 15%);
background-image: linear-gradient(#eee 1%, #fff 15%);
cursor: text
}
.chosen-container-multi .chosen-choices li {
float: left;
list-style: none
}
.chosen-container-multi .chosen-choices li.search-field {
margin: 0;
padding: 0;
white-space: nowrap
}
.chosen-container-multi .chosen-choices li.search-field input[type=text] {
margin: 1px 0;
padding: 5px;
height: 15px;
outline: 0;
border: 0!important;
background: 0 0!important;
box-shadow: none;
color: #666;
font-size: 100%;
font-family: sans-serif;
line-height: normal;
border-radius: 0
}
.chosen-container-multi .chosen-choices li.search-field .default {
color: #999
}
.chosen-container-multi .chosen-choices li.search-choice {
position: relative;
margin: 3px 0 3px 5px;
padding: 3px 20px 3px 5px;
border: 1px solid #aaa;
border-radius: 3px;
background-color: #e4e4e4;
background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));
background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-clip: padding-box;
box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, .05);
color: #333;
line-height: 13px;
cursor: default
}
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
position: absolute;
top: 4px;
right: 3px;
display: block;
width: 12px;
height: 12px;
background: url(../images/chosen-sprite.png) -42px 1px no-repeat;
font-size: 1px
}
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
background-position: -42px -10px
}
.chosen-container-multi .chosen-choices li.search-choice-disabled {
padding-right: 5px;
border: 1px solid #ccc;
background-color: #e4e4e4;
background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));
background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
color: #666
}
.chosen-container-multi .chosen-choices li.search-choice-focus {
background: #d4d4d4
}
.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
background-position: -42px -10px
}
.chosen-container-multi .chosen-results {
margin: 0;
padding: 0
}
.chosen-container-multi .chosen-drop .result-selected {
display: list-item;
color: #ccc;
cursor: default
}
.chosen-container-active .chosen-single {
border: 1px solid #5897fb;
box-shadow: 0 0 5px rgba(0, 0, 0, .3)
}
.chosen-container-active.chosen-with-drop .chosen-single {
border: 1px solid #aaa;
-moz-border-radius-bottomright: 0;
border-bottom-right-radius: 0;
-moz-border-radius-bottomleft: 0;
border-bottom-left-radius: 0;
background-image: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(20%, #eee), color-stop(80%, #fff));
background-image: -webkit-linear-gradient(#eee 20%, #fff 80%);
background-image: -moz-linear-gradient(#eee 20%, #fff 80%);
background-image: -o-linear-gradient(#eee 20%, #fff 80%);
background-image: linear-gradient(#eee 20%, #fff 80%);
box-shadow: 0 1px 0 #fff inset
}
.chosen-container-active.chosen-with-drop .chosen-single div {
border-left: none;
background: 0 0
}
.chosen-container-active.chosen-with-drop .chosen-single div b {
background-position: -18px 2px
}
.chosen-container-active .chosen-choices {
border: 1px solid #5897fb;
box-shadow: 0 0 5px rgba(0, 0, 0, .3)
}
.chosen-container-active .chosen-choices li.search-field input[type=text] {
color: #111!important
}
.chosen-disabled {
opacity: .5!important;
cursor: default
}
.chosen-disabled .chosen-choices .search-choice .search-choice-close,
.chosen-disabled .chosen-single {
cursor: default
}
.chosen-rtl {
text-align: right
}
.chosen-rtl .chosen-single {
overflow: visible;
padding: 0 8px 0 0
}
.chosen-rtl .chosen-single span {
margin-right: 0;
margin-left: 26px;
direction: rtl
}
.chosen-rtl .chosen-single-with-deselect span {
margin-left: 38px
}
.chosen-rtl .chosen-single div {
right: auto;
left: 3px
}
.chosen-rtl .chosen-single abbr {
right: auto;
left: 26px
}
.chosen-rtl .chosen-choices li {
float: right
}
.chosen-rtl .chosen-choices li.search-field input[type=text] {
direction: rtl
}
.chosen-rtl .chosen-choices li.search-choice {
margin: 3px 5px 3px 0;
padding: 3px 5px 3px 19px
}
.chosen-rtl .chosen-choices li.search-choice .search-choice-close {
right: auto;
left: 4px
}
.chosen-rtl .chosen-drop,
.chosen-rtl.chosen-container-single-nosearch .chosen-search {
left: 9999px
}
.chosen-rtl.chosen-container-single .chosen-results {
margin: 0 0 4px 4px;
padding: 0 4px 0 0
}
.chosen-rtl .chosen-results li.group-option {
padding-right: 15px;
padding-left: 0
}
.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {
border-right: none
}
.chosen-rtl .chosen-search input[type=text] {
padding: 4px 5px 4px 20px;
background: url(../images/chosen-sprite.png) -30px -20px no-repeat #fff;
background: url(../images/chosen-sprite.png) -30px -20px no-repeat, -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
background: url(../images/chosen-sprite.png) -30px -20px no-repeat, -webkit-linear-gradient(#eee 1%, #fff 15%);
background: url(../images/chosen-sprite.png) -30px -20px no-repeat, -moz-linear-gradient(#eee 1%, #fff 15%);
background: url(../images/chosen-sprite.png) -30px -20px no-repeat, -o-linear-gradient(#eee 1%, #fff 15%);
background: url(../images/chosen-sprite.png) -30px -20px no-repeat, linear-gradient(#eee 1%, #fff 15%);
direction: rtl
}
.chosen-rtl.chosen-container-single .chosen-single div b {
background-position: 6px 2px
}
.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {
background-position: -12px 2px
}
@media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min-resolution: 144dpi) {
.chosen-container .chosen-results-scroll-down span,
.chosen-container .chosen-results-scroll-up span,
.chosen-container-multi .chosen-choices .search-choice .search-choice-close,
.chosen-container-single .chosen-search input[type=text],
.chosen-container-single .chosen-single abbr,
.chosen-container-single .chosen-single div b,
.chosen-rtl .chosen-search input[type=text] {
background-image: url(../images/chosen-sprite@2x.png)!important;
background-size: 52px 37px!important;
background-repeat: no-repeat!important
}
}
#cc_list_chosen .search-field input {
width: 100% !important;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
.ui-timepicker-div dl { text-align: left; }
.ui-timepicker-div dl dt { float: left; clear:left; padding: 0 0 0 5px; }
.ui-timepicker-div dl dd { margin: 0 10px 10px 40%; }
.ui-timepicker-div td { font-size: 90%; }
.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
.ui-timepicker-div .ui_tpicker_unit_hide{ display: none; }
.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input { background: none; color: inherit; border: none; outline: none; border-bottom: solid 1px #555; width: 95%; }
.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus { border-bottom-color: #aaa; }
.ui-timepicker-rtl{ direction: rtl; }
.ui-timepicker-rtl dl { text-align: right; padding: 0 5px 0 0; }
.ui-timepicker-rtl dl dt{ float: right; clear: right; }
.ui-timepicker-rtl dl dd { margin: 0 40% 10px 10px; }
/* Shortened version style */
.ui-timepicker-div.ui-timepicker-oneLine { padding-right: 2px; }
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,
.ui-timepicker-div.ui-timepicker-oneLine dt { display: none; }
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label { display: block; padding-top: 2px; }
.ui-timepicker-div.ui-timepicker-oneLine dl { text-align: right; }
.ui-timepicker-div.ui-timepicker-oneLine dl dd,
.ui-timepicker-div.ui-timepicker-oneLine dl dd > div { display:inline-block; margin:0; }
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before { content:':'; display:inline-block; }
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before,
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before { content:'.'; display:inline-block; }
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide,
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{ display: none; }

View File

@@ -0,0 +1,6 @@
/* phpcs:ignoreFile */
/*! jQuery Timepicker Addon - v1.6.3 - 2016-04-20
* http://trentrichardson.com/examples/timepicker
* Copyright (c) 2016 Trent Richardson; Licensed MIT */
.ui-timepicker-div .ui-widget-header{margin-bottom:8px}.ui-timepicker-div dl{text-align:left}.ui-timepicker-div dl dt{float:left;clear:left;padding:0 0 0 5px}.ui-timepicker-div dl dd{margin:0 10px 10px 40%}.ui-timepicker-div td{font-size:90%}.ui-tpicker-grid-label{background:0 0;border:0;margin:0;padding:0}.ui-timepicker-div .ui_tpicker_unit_hide{display:none}.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input{background:0 0;color:inherit;border:0;outline:0;border-bottom:solid 1px #555;width:95%}.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus{border-bottom-color:#aaa}.ui-timepicker-rtl{direction:rtl}.ui-timepicker-rtl dl{text-align:right;padding:0 5px 0 0}.ui-timepicker-rtl dl dt{float:right;clear:right}.ui-timepicker-rtl dl dd{margin:0 40% 10px 10px}.ui-timepicker-div.ui-timepicker-oneLine{padding-right:2px}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,.ui-timepicker-div.ui-timepicker-oneLine dt{display:none}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label{display:block;padding-top:2px}.ui-timepicker-div.ui-timepicker-oneLine dl{text-align:right}.ui-timepicker-div.ui-timepicker-oneLine dl dd,.ui-timepicker-div.ui-timepicker-oneLine dl dd>div{display:inline-block;margin:0}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before{content:':';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before{content:'.';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide,.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{display:none}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,438 @@
/* phpcs:ignoreFile */
/* Smart Coupons Style */
.coupon-container {
line-height: 1.4em;
position: relative;
display: inline-table;
margin: 2px;
padding: .55em;
cursor: pointer;
text-align: center;
box-shadow: 0 0 5px #e0e0e0;
}
.coupon-container.previews {
cursor: inherit;
}
.coupon-content {
padding: .2em 1.2em;
}
.coupon-content .code {
font-family: monospace;
font-size: 1.2em;
font-weight: 700;
}
.coupon-content .coupon-expire,
.coupon-content .discount-info {
font-family: Helvetica, Arial, sans-serif;
font-size: 1em;
}
.coupon-content .discount-description {
font: .7em/1 Helvetica, Arial, sans-serif;
display: inline-block;
margin: 10px inherit;
}
.wc-sc-coupon-style-preview .coupon-container {
display: inline-block;
}
span.wc-sc-coupon-preview-container {
position: absolute;
display: inline-block;
margin: 0 0 0 1em;
font-size: initial;
}
.wc_sc_custom_design_css_doc_div {
margin: 15px 0;
}
/*Shortcode fields*/
#coupon-selector #coupon-option label span {
display: inline-block;
width: 100px;
}
#coupon-selector #coupon-option label select {
width: 175px;
margin-bottom: 6px;
margin-left: -.2em;
}
div#sc_shortcode_update {
float: right;
margin-top: -5px;
}
form#sc_coupons_attributes {
padding: 0 1em 1em;
}
div#coupon-selector {
float: left;
padding: 1em 1em 1em 0;
border-right: 1px solid #e6e6e6;
}
.coupon-preview {
float: left;
width: 175px;
padding: 1em 0 1em 1em;
}
.preview-heading {
font-size: 15px;
padding-bottom: 10px;
text-align: center;
}
#search-panel {
overflow-x: hidden;
width: 275px;
min-height: 80px;
max-height: 110px;
margin: 5px 0;
color: #333;
border: 1px solid #d4d4d4;
background-color: #fff;
}
#coupon-option #search-panel #search-results span {
width: 100%;
margin-left: 10px;
}
#search-results ul {
margin: 5px -2px;
}
#search-results ul li {
font-size: 12px;
margin-bottom: -1px;
padding: 3px 15px;
cursor: pointer;
border: 1px solid #f2f2f2;
}
#search-results ul li:hover {
color: #000;
background-color: #eaf2fa;
}
#coupon-option #search-panel #search-results ul li span {
width: 0;
color: #f00;
}
#sc_coupons_attributes .submitbox {
clear: both;
}
#default-text {
font-style: italic;
margin-bottom: -5px;
padding: 2px;
text-align: center;
background-color: #f2f2f2;
}
/* Gift Cerificate form */
input.gift_receiver_email, input.gift_sending_date_time {
min-width: 100%;
margin: 1% 0;
}
div#gift-certificate-receiver-form thead th {
text-align: center;
}
input#deliver_on_date {
text-align: center;
}
.email_sending_date_time_wrapper:not(.show),
.wc_sc_schedule_gift_sending_wrapper:not(.show) {
display: none;
}
.wc_sc_schedule_gift_sending_wrapper.show {
margin-left: 2em;
}
/* Coupon generation form */
form#generate_coupons p.form-field input[type=text] {
width: 30%;
}
form#generate_coupons p.form-field input[type=number] {
width: 15%;
}
form#generate_coupons p.form-field input[name="wc_sc_max_discount"] {
width: 30%;
}
div.gift-certificate-receiver-detail-form,
div#gift-certificate-receiver-form-multi {
display: none;
}
a#single_multi {
float: right;
}
.sc_info_box {
overflow: hidden;
margin-bottom: 2em !important;
padding: .5em 1em 0 !important;
background-color: #f7f6f7;
}
tr.wc_sc_custom_design_css_wrapper .CodeMirror + span.wc-sc-coupon-preview-container {
top: 15px;
}
tr.wc_sc_custom_design_css_wrapper td.forminp.forminp-textarea {
position: relative;
}
tr.wc_sc_custom_design_css_wrapper .CodeMirror {
width: 100%;
max-width: 400px;
height: 200px;
}
.sc-coupons-list details > summary {
list-style: none;
}
.sc-coupons-list details > summary::marker, /* Latest Chrome, Edge, Firefox */
.sc-coupons-list details > summary::-webkit-details-marker /* Safari */ {
display: none;
}
@media (min-width: 768px) {
.sc_info_box {
float: unset !important;
width: unset !important;
margin-right: unset !important;
padding: .5em 1em 0 !important;
}
.page-template-template-fullwidth-php .sc_info_box {
float: unset !important;
width: unset !important;
margin-right: unset !important;
margin-left: unset !important;
padding: .5em 1em 0 !important;
}
/* Fix for positioning 'Sell store credit at less price?' settings' tooltip */
label[for="smart_coupons_sell_store_credit_at_less_price"] span.woocommerce-help-tip,
label[for="smart_coupons_schedule_store_credit"] span.woocommerce-help-tip {
float: left;
margin: 1px 4px 1px -1.7em !important;
}
tr.wc_sc_custom_design_css_wrapper .CodeMirror + span.wc-sc-coupon-preview-container {
left: 415px;
}
}
textarea.gift_receiver_message {
width: 100%;
}
.form_table {
width: 97%;
padding: 20px 10px;
border-top: 2px;
border-top-style: solid;
border-top-color: #dbdbdb;
}
.message_row {
width: 100%;
}
.sc_message {
width: 100%;
}
.email_amount {
width: 100%;
}
.gift-certificate-show-form p {
margin: 0;
}
.gift-certificate-show-form lable {
display: inline;
}
.gift-certificate-show-form input[type=radio] {
margin-left: 1em;
}
.show_hide_list {
padding-left: 0;
margin-left: 25px;
}
.single_multi_list {
display: none;
}
div.mce-smart-coupon-shortcode {
cursor: pointer;
}
div.mce-smart-coupon-shortcode i:before {
font-family: 'WooCommerce';
content: '\e600';
}
div[aria-describedby='sc_coupons_attributes'] {
z-index: 1000;
}
.wc_sc_total_available_store_credit {
padding: 1em 0;
text-align: right;
}
.wc_sc_total_available_store_credit .amount {
font-size: 1.5em;
font-weight: bold;
}
div#invalid_coupons_list div#all_coupon_container .coupon-container {
cursor: initial !important;
opacity: .5;
}
div#invalid_coupons_list div#all_coupon_container .coupon-container .coupon-content .coupon-expire {
display: none;
}
.variation-sc_called_credit {
display: none;
}
/* Bulk Generate tab - Coupon Description */
.sc_bulk_description textarea#woocommerce-coupon-description {
width: 90%;
margin-left: 0.5em;
}
#call_for_credit {
position: relative;
}
input#credit_called {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.wc-sc-call-for-credit-container .wc-sc-label,
.wc-sc-call-for-credit-container .wc-sc-input {
width: 48%;
float: left;
}
.wc-sc-call-for-credit-container .wc-sc-row {
position: relative;
margin-top: 1em;
}
.wc-sc-call-for-credit-container .wc-sc-row:after {
content: "";
display: table;
clear: both;
}
.wc-sc-description {
display: inline-block;
}
#sc-cc input {
border: 1px solid #7e8993;
}
#sc-cc .sc-truncate {
overflow: hidden;
text-overflow: ellipsis;
height: 2rem;
}
.forminp-wc_sc_radio_with_html {
border-collapse: initial;
}
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design li {
padding: 10px 10px 5px 5px;
}
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design li input,
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design_colors li input {
vertical-align: top;
}
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design_colors.custom li input[type="color"] {
opacity: 0;
display: block;
width: 32px;
height: 20px;
border: none;
cursor: pointer;
}
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design_colors li span {
display: inline-block;
width: 32px;
height: 20px;
vertical-align: middle;
}
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design,
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design_colors {
margin-top: unset;
}
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design li,
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design_colors li {
cursor: pointer;
}
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design_colors li {
display: inline-block;
width: 150px;
padding: 5px;
}
.forminp-wc_sc_radio_with_html ul li:hover,
.forminp-wc_sc_radio_with_html ul li.selected {
background: #ddd;
}
.forminp-wc_sc_radio_with_html .wc_sc_setting_coupon_design {
align-items: unset !important;
}
@media screen and (max-width: 767px) {
.wc-sc-description {
margin-left: 0;
}
tr.wc_sc_custom_design_css_wrapper .CodeMirror + span.wc-sc-coupon-preview-container {
position: static;
margin-top: 15px;
}
}
@media screen and (min-width: 768px) and (max-width: 799px) {
.wc-sc-description {
margin-left: 5%;
}
}
@media screen and (min-width: 800px) and (max-width: 1023px) {
.wc-sc-description {
margin-left: 7%;
}
}
@media screen and (min-width: 1024px) and (max-width: 1199px) {
.wc-sc-description {
margin-left: 11%;
}
}
@media screen and (min-width: 1200px) and (max-width: 1279px) {
.wc-sc-description {
margin-left: 14%;
}
}
@media screen and (min-width: 1280px) and (max-width: 1365px) {
.wc-sc-description {
margin-left: 15%;
}
}
@media screen and (min-width: 1366px) and (max-width: 1599px) {
.wc-sc-description {
margin-left: 16%;
}
}
@media screen and (min-width: 1600px) {
.wc-sc-description {
margin-left: 20%;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,50 @@
/* phpcs:ignoreFile */
/* Smart Coupons Admin CSS */
.smart-coupons-field,
#sc-share-link,
#sc_coupon_categorydiv,
#sc_coupon_categorydiv ul.category-tabs li.tabs,
#sc_coupon_categorydiv ul.add-menu-item-tabs li.tabs,
#sc_coupon_categorydiv .wp-tab-active,
#sc_coupon_categorydiv div.tabs-panel,
button#export_coupons,
a#wc_sc_print_coupons,
a#sc-manage-category,
#wc-sc-copy-coupon-code {
background-color: #f0fff0;
}
button#export_coupons > span.dashicons,
a#wc_sc_print_coupons > span.dashicons,
a#sc-manage-category > span.dashicons {
transform: translateX(-15%) translateY(15%);
}
div#smart_coupons_tabs h2 {
margin-bottom: 10px;
}
div#smart_coupons_tabs h2 .sc-quick-links {
text-align: right;
font-size: 0.8em;
}
.coupon_title_prefix_suffix_field input {
height: 2em;
}
li.wc_sc_actions_tab a::before {
font-family: WooCommerce !important;
content: '\e01c' !important;
}
div.sc-manage-category {
margin: 10px 0;
}
div.sc-manage-category a {
font-weight: 600;
}
div.smart_coupons_product_options_variable {
display: flow-root;
}
table.wp-list-table .column-wc_sc_linked_coupons {
width: 10% !important;
}
#sc-generated-coupon-data,
#woocommerce-order-actions select[name="wc_order_action"] option[value^="wc_sc_"] {
background-color: #f0fff0;
}

View File

@@ -0,0 +1,2 @@
/* phpcs:ignoreFile */
.smart-coupons-field,#sc-share-link,#sc_coupon_categorydiv,#sc_coupon_categorydiv ul.category-tabs li.tabs,#sc_coupon_categorydiv ul.add-menu-item-tabs li.tabs,#sc_coupon_categorydiv .wp-tab-active,#sc_coupon_categorydiv div.tabs-panel,button#export_coupons,a#wc_sc_print_coupons,a#sc-manage-category,#wc-sc-copy-coupon-code{background-color:#f0fff0}button#export_coupons>span.dashicons,a#wc_sc_print_coupons>span.dashicons,a#sc-manage-category>span.dashicons{transform:translateX(-15%) translateY(15%)}div#smart_coupons_tabs h2{margin-bottom:10px}div#smart_coupons_tabs h2 .sc-quick-links{text-align:right;font-size:.8em}.coupon_title_prefix_suffix_field input{height:2em}li.wc_sc_actions_tab a::before{font-family:WooCommerce!important;content:'\e01c'!important}div.sc-manage-category{margin:10px 0}div.sc-manage-category a{font-weight:600}div.smart_coupons_product_options_variable{display:flow-root}table.wp-list-table .column-wc_sc_linked_coupons{width:10%!important}#sc-generated-coupon-data,#woocommerce-order-actions select[name=wc_order_action] option[value^=wc_sc_]{background-color:#f0fff0}

View File

@@ -0,0 +1,22 @@
/* Coupon style for email-coupon */
.coupon-container.email-coupon .coupon-content {
border: 1px solid !important;
border-style: dashed !important;
}
.coupon-container.email-coupon {
transition-duration: .3s !important;
transition-property: border-radius !important;
-webkit-transform: perspective(1px) translateZ(0) !important;
transform: perspective(1px) translateZ(0) !important;
border-radius: .8em !important;
box-shadow: 0 0 1px rgba(0, 0, 0, 0) !important;
display: table;
margin: 0 auto;
}
.coupon-container.email-coupon:hover,
.coupon-container.email-coupon:focus,
.coupon-container.email-coupon:active {
border-radius: 0 !important;
}

View File

@@ -0,0 +1,2 @@
/* phpcs:ignoreFile */
.coupon-container.email-coupon .coupon-content{border:1px solid !important;border-style:dashed !important}.coupon-container.email-coupon{transition-duration:.3s !important;transition-property:border-radius !important;-webkit-transform:perspective(1px) translateZ(0) !important;transform:perspective(1px) translateZ(0) !important;border-radius:.8em !important;box-shadow:0 0 1px rgba(0,0,0,0) !important;display:table;margin:0 auto}.coupon-container.email-coupon:hover,.coupon-container.email-coupon:focus,.coupon-container.email-coupon:active{border-radius:0 !important}

View File

@@ -0,0 +1 @@
<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><path d="m51.9 23.4c.3 1-.2 2.1-1.2 2.5l-19 6.2h-11.9l-2.6-8h24.8c1.1 0 2-.9 2-2v-7h3c-.1 2.1 1.4 3.8 3.5 4z" fill="#e9edf5"/><path d="m41 11c-.5 0-1 .2-1.4.6-.1.1-.2.2-.2.3-.8-.3-1.3-1-1.3-1.9h-22.1c0 1.1-.9 2-2 2v6c1.1 0 2 .9 2 2h22c0-1.1.9-2 2-2v-3.3c.3.2.6.3 1 .3h3v7c0 1.1-.9 2-2 2h-30c-1.1 0-2-.9-2-2v-14c0-1.1.9-2 2-2h30c1.1 0 2 .9 2 2v3z" fill="#7e8596"/><path d="m40 14.7v3.3c-1.1 0-2 .9-2 2h-22c0-1.1-.9-2-2-2v-6c1.1 0 2-.9 2-2h22c0 .8.5 1.6 1.3 1.9-.2.3-.3.7-.3 1.1 0 .7.4 1.4 1 1.7z" fill="#f2f6fc"/><path d="m16 18v-6c1.1 0 2-.9 2-2h-2c0 1.1-.9 2-2 2v6c1.1 0 2 .9 2 2h2c0-1.1-.9-2-2-2z" fill="#dce1eb"/><path d="m44 11v-3c0-1.1-.9-2-2-2h-10l9-5 18 3h4v11h-4s0 4-4 4h-4c-.2 0-.4 0-.5 0-2-.2-3.6-1.9-3.5-3.9h-6c-1.1 0-2-.9-2-2 0-.4.1-.8.3-1.1.1-.1.2-.2.2-.3.5-.5 1-.7 1.5-.7z" fill="#ffcdbe"/><path d="m41 1-9 5h3l8.3-4.6z" fill="#ffbeaa"/><path d="m47 8c0-1.1-.9-2-2-2h-3c1.1 0 2 .9 2 2v3h3zm-5 5c0-.4.1-.8.3-1.1.1-.1.2-.2.2-.3.5-.4 1-.6 1.5-.6h-3c-.5 0-1 .2-1.4.6-.1.1-.2.2-.2.3-.3.3-.4.7-.4 1.1 0 1.1.9 2 2 2h3c-1.1 0-2-.9-2-2zm8 2h-3c-.1 2.1 1.4 3.8 3.5 4h.5 3c-.2 0-.4 0-.5 0-2.1-.2-3.6-2-3.5-4z" fill="#ffbeaa"/><path d="m23.7 42c.2.3.3.6.3 1 0 .7-.3 1.4-.9 1.7l-16.5 12.1-2.5 1.9c-1 .6-2.2.3-2.8-.7-.2-.3-.3-.6-.3-1 0-.7.3-1.4.9-1.7l3.8-2.8 15.3-11.2c.3-.2.6-.3 1-.3.7 0 1.3.4 1.7 1zm27.3 15c0 .4-.1.7-.3 1.1-.6.9-1.8 1.2-2.8.6l-2.5-1.9-16.5-12.1c-.6-.4-1-1-.9-1.7 0-.4.1-.7.3-1 .4-.6 1-1 1.7-1 .4 0 .7.1 1.1.3l15.2 11.1 3.8 2.8c.6.4.9 1.1.9 1.8z" fill="#7e8596"/><path d="m3.3 58c-.2-.3-.3-.6-.3-1 0-.7.3-1.4.9-1.7l3.8-2.8 15.3-11.2h.1c-.4-.2-.7-.3-1.1-.3s-.7.1-1.1.3l-15.1 11.2-3.8 2.8c-.6.4-1 1-.9 1.7 0 .4.1.7.3 1.1.5.9 1.7 1.2 2.6.6-.3-.1-.5-.4-.7-.7zm46.7.7-2.5-1.9-16.6-12.1c-.6-.4-1-1-.9-1.7 0-.4.1-.7.3-1s.4-.5.7-.7c-.9-.5-2.1-.2-2.7.7-.2.3-.3.6-.3 1 0 .7.3 1.4.9 1.7l16.5 12.1 2.6 1.9c.6.4 1.4.4 2 0z" fill="#636978"/><path d="m21 53h10c1.1 0 2 .9 2 2v2c0 1.1-.9 2-2 2h-10c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2z" fill="#ff808c"/><path d="m22 57v-2c0-1.1.9-2 2-2h-3c-1.1 0-2 .9-2 2v2c0 1.1.9 2 2 2h3c-1.1 0-2-.9-2-2z" fill="#f25a6b"/><path d="m51 34v2c0 1.1-.9 2-2 2h-46c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2h46c1.1 0 2 .9 2 2z" fill="#ff808c"/><path d="m4 36v-2c0-1.1.9-2 2-2h-3c-1.1 0-2 .9-2 2v2c0 1.1.9 2 2 2h3c-1.1 0-2-.9-2-2z" fill="#f25a6b"/><path d="m30 41c.4 0 .7.1 1.1.3l15.2 11.1 2.7-14.4h-46l2.8 14.5 15.2-11.2c.3-.2.6-.3 1-.3.7 0 1.3.4 1.7 1 .2.3.3.6.3 1 0 .7-.3 1.4-.9 1.7l-16.5 12.1.4 2.2c0 2.2 1.8 4 4 4h30c2.2 0 4-1.8 4-4l.4-2.2-16.5-12.1c-.6-.4-1-1-.9-1.7 0-.4.1-.7.3-1 .4-.6 1-1 1.7-1zm1 12c1.1 0 2 .9 2 2v2c0 1.1-.9 2-2 2h-10c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2z" fill="#e9edf5"/><path d="m6 38h-3l2.8 14.5 2.6-1.9z" fill="#cdd2e1"/><path d="m6.6 56.8.4 2.2c0 2.2 1.8 4 4 4h3c-2.2 0-4-1.8-4-4l-.8-4.1z" fill="#cdd2e1"/><g fill="none" stroke="#404040" stroke-linejoin="round"><path d="m42 38h-2"/><path d="m38 38h-35c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2h46c1.1 0 2 .9 2 2v2c0 1.1-.9 2-2 2h-5"/><path d="m6.6 56.8.4 2.2c0 2.2 1.8 4 4 4h30c2.2 0 4-1.8 4-4l.4-2.2"/><path d="m49 38-2.8 14.5"/><path d="m5.8 52.5-2.8-14.5"/><path d="m22 41c.7 0 1.3.4 1.7 1 .2.3.3.6.3 1 0 .7-.3 1.4-.9 1.7l-16.5 12.1-2.5 1.9c-1 .6-2.2.3-2.8-.7-.2-.3-.3-.6-.3-1 0-.7.3-1.4.9-1.7l3.8-2.8 15.3-11.2c.3-.2.6-.3 1-.3zm8 0c-.7 0-1.3.4-1.7 1-.2.3-.3.6-.3 1 0 .7.3 1.4.9 1.7l16.5 12.1 2.6 1.9c.9.6 2.2.3 2.8-.6.2-.3.3-.7.2-1 0-.7-.3-1.4-.9-1.7l-3.8-2.8-15.3-11.3c-.3-.2-.6-.3-1-.3z"/><path d="m21 53h10c1.1 0 2 .9 2 2v2c0 1.1-.9 2-2 2h-10c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2z"/><path d="m63 15h-4s0 4-4 4h-4c-.2 0-.4 0-.5 0-2-.2-3.6-1.9-3.5-3.9h-6c-1.1 0-2-.9-2-2 0-.4.1-.8.3-1.1.1-.1.2-.2.2-.3.5-.5 1-.7 1.5-.7h6"/><path d="m32 6 9-5 18 3h4"/><path d="m44 15v7c0 1.1-.9 2-2 2h-30c-1.1 0-2-.9-2-2v-14c0-1.1.9-2 2-2h30c1.1 0 2 .9 2 2v3"/><path d="m55 31 4-4"/><path d="m59 43-4-4"/><path d="m55 35h7"/><path d="m40 14.7v3.3c-1.1 0-2 .9-2 2h-22c0-1.1-.9-2-2-2v-6c1.1 0 2-.9 2-2h22c0 .8.5 1.6 1.3 1.9"/><path d="m19.8 32-2.6-8"/><path d="m50.5 19 1.4 4.4c.3 1-.2 2.1-1.2 2.5l-19 6.1"/></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -0,0 +1 @@
<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><path d="m45 38h-30c-.6 0-1-.4-1-1s.4-1 1-1h30c.6 0 1 .4 1 1s-.4 1-1 1zm1-5h-35c-.6 0-1-.4-1-1s.4-1 1-1h35c.6 0 1 .4 1 1s-.4 1-1 1zm2-5h-40c-.6 0-1-.4-1-1s.4-1 1-1h40c.6 0 1 .4 1 1s-.4 1-1 1z" fill="#f7b957"/><path d="m63 12h-8.5c-1.3 0-2.4.8-2.8 2.1l-2 5.9h-46.7c-1.7 0-3 1.3-3 3v.6c0 .4.1.7.2 1l6.4 17.2c.4 1.4 1.6 2.2 2.9 2.2h32.3l-.7 2.1c-.4 1.2-1.6 1.9-2.8 1.9h-28.3c-1.7 0-3 1.3-3 3v5c0 .6.4 1 1 1s1-.4 1-1v-5c0-.6.4-1 1-1h22.2c-.1.3-.2.7-.2 1v5c0 .6.4 1 1 1s1-.4 1-1v-5c0-.6.4-1 1-1h3.3c2.1 0 3.9-1.3 4.7-3.2l10.6-32.1c.1-.4.6-.7 1-.7h8.4c.6 0 1-.4 1-1s-.4-1-1-1zm-20.6 30h-32.9c-.5 0-.9-.3-1-.7l-6.4-17.3c-.1-.1-.1-.2-.1-.4v-.6c0-.6.4-1 1-1h46z" fill="#f7b957"/><circle cx="11" cy="56" fill="#a8b7d4" r="3"/><circle cx="36" cy="56" fill="#a8b7d4" r="3"/><path d="m11 60c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm25 6c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" fill="#404040"/><path d="m39.1 21c.7-.6 1.9-1.2 1.9-2 0-1-2.2-1.8-2.4-2.7s1.4-2.6 1-3.5-2.7-.6-3.3-1.4.2-3-.6-3.6-2.6.6-3.5.2-1.1-2.8-2.1-3-2.1 1.8-3.1 1.8-2.2-2-3.1-1.8-1.2 2.5-2 3-2.9-.8-3.6-.2 0 2.8-.6 3.6-2.9.5-3.3 1.4 1.2 2.5 1 3.5-2.4 1.7-2.4 2.7c0 .8 1.2 1.4 1.9 2 .2.2.4.4.5.7.2 1-1.4 2.6-1 3.5s2.7.6 3.3 1.4-.2 3 .6 3.6 2.7-.6 3.5-.2 1.1 2.8 2.1 3 2.1-1.8 3.1-1.8 2.2 2 3.1 1.8 1.2-2.5 2-3c.9-.5 2.8.8 3.6.2s0-2.8.6-3.6 2.9-.5 3.3-1.4-1.2-2.5-1-3.5c.1-.3.3-.5.5-.7z" fill="#d23b54"/><path d="m37.4 20.7c.6-.5 1.6-1.1 1.6-1.7 0-.9-1.8-1.5-2-2.3s1.2-2.2.8-3-2.3-.5-2.8-1.2.1-2.6-.5-3.1-2.3.6-3 .2-1-2.4-1.8-2.6-1.8 1.5-2.7 1.5-1.9-1.7-2.7-1.5-1 2.2-1.8 2.6-2.4-.7-3-.2 0 2.4-.5 3.1-2.5.4-2.8 1.2 1 2.2.9 3-2 1.5-2 2.3c0 .6 1 1.2 1.6 1.7.2.2.4.4.4.6.2.8-1.2 2.2-.9 3s2.3.5 2.8 1.2-.1 2.5.5 3.1 2.3-.5 3-.2 1 2.4 1.8 2.5 1.8-1.5 2.7-1.5 1.9 1.7 2.7 1.5 1-2.2 1.8-2.5 2.4.7 3 .2 0-2.4.5-3.1 2.5-.4 2.8-1.2-1-2.2-.8-3c0-.2.2-.4.4-.6z" fill="#d23b54"/><path d="m21 26c-.3 0-.5-.1-.7-.3-.4-.4-.4-1 0-1.4l12-12c.4-.4 1-.4 1.4 0s.4 1 0 1.4l-12 12c-.2.2-.4.3-.7.3zm9 1c-1.7 0-3-1.3-3-3s1.3-3 3-3 3 1.3 3 3-1.3 3-3 3zm0-4c-.6 0-1 .4-1 1s.4 1 1 1 1-.4 1-1-.4-1-1-1zm-6-6c-1.7 0-3-1.3-3-3s1.3-3 3-3 3 1.3 3 3-1.3 3-3 3zm0-4c-.6 0-1 .4-1 1s.4 1 1 1 1-.4 1-1-.4-1-1-1z" fill="#fbfbfb"/></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"><path d="m31 13h-4a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z" fill="#919191"/><path d="m15 34a6 6 0 1 1 -9.12-5.12 6 6 0 0 1 9.12 5.12z" fill="#374f68"/><path d="m14.12 37.12c-5.3 3.26-11.53-2.9-8.24-8.24 5.32-3.28 11.51 2.93 8.24 8.24z" fill="#425b72"/><path d="m11 34a2 2 0 1 1 -2.82-1.82 2 2 0 0 1 2.82 1.82z" fill="#dad7e5"/><path d="m10.82 34.82a2 2 0 0 1 -2.64-2.64 2 2 0 0 1 2.64 2.64z" fill="#edebf2"/><path d="m47 34a6 6 0 1 1 -9.12-5.12 6 6 0 0 1 9.12 5.12z" fill="#374f68"/><path d="m46.12 37.12c-5.3 3.26-11.53-2.9-8.24-8.24 5.32-3.28 11.51 2.93 8.24 8.24z" fill="#425b72"/><path d="m43 34a2 2 0 1 1 -2.82-1.82 2 2 0 0 1 2.82 1.82z" fill="#dad7e5"/><path d="m42.82 34.82a2 2 0 0 1 -2.64-2.64 2 2 0 0 1 2.64 2.64z" fill="#edebf2"/><path d="m47 30.5c-1.16.67-.17.5-5.2.5-3.07 0-2.53 3-5.6 3h-2.26c0-7.16 9.54-9.67 13.06-3.5z" fill="#ffba55"/><path d="m45.84 29c-2.09 0-3.58-.28-4.9 1.58a3.37 3.37 0 0 1 -2.74 1.42 1.88 1.88 0 0 1 -1.79-2.52 6.83 6.83 0 0 1 .67-1.32 7 7 0 0 1 8.76.84z" fill="#fc6"/><path d="m22.4 21.4c-.83.81-1.14.6-7.4.6v-4.5l6.07.38a2.07 2.07 0 0 1 1.33 3.52z" fill="#7c7d7d"/><path d="m23 20h-3.63a2.37 2.37 0 0 1 -2.37-2.37l4.07.25a2.07 2.07 0 0 1 1.93 2.12z" fill="#919191"/><path d="m38 9v4a1 1 0 0 1 -1 1h-5a1 1 0 0 1 -1-1 5 5 0 0 1 2.61-4.39 6 6 0 0 1 3.39-.61 1 1 0 0 1 1 1z" fill="#ffba55"/><path d="m38 9v3h-4c-1.46 0-1.06-2.16-.39-3.39a6 6 0 0 1 3.39-.61 1 1 0 0 1 1 1z" fill="#fc6"/><path d="m40.21 27a7 7 0 0 0 -6.27 7h-14.94a4.39 4.39 0 0 0 -4.16-3h-12.72a1 1 0 0 1 -1-1.11l.39-3.44a5 5 0 0 1 5-4.45h14.49l2 8h8a15.06 15.06 0 0 0 1.51-14.86l-.51-1.14h4c2.19 4.37 4 7.44 4.21 13z" fill="#fc6"/><path d="m40.21 27a7 7 0 0 0 -6 5h-13.21a4.39 4.39 0 0 0 -4.16-3h-12.72a1 1 0 0 1 -1-1.11c.37-3.3.34-4.11 1-5.28 1.47-.83.88-.61 16.88-.61l2 8h8a15.09 15.09 0 0 0 1.51-14.86l-.51-1.14h4c2.11 4.22 4.1 7.59 4.21 13z" fill="#ffde76"/><path d="m42 11a2.35 2.35 0 0 1 -2.34 2.34 6.42 6.42 0 0 1 -1.66-.34v-4l1-.25a2.35 2.35 0 0 1 3 2.25z" fill="#9fdbf3"/><path d="m41.74 12.07c-1 .5-1.67.19-2.74-.07 0-3.61 0-3.24.09-3.27a2.34 2.34 0 0 1 2.65 3.34z" fill="#b2e5fb"/><path d="m11 28h-4a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z" fill="#ffba55"/><path d="m1 10h14v12h-14z" fill="#df8761"/><path d="m15 10v10h-9a3 3 0 0 1 -3-3v-7z" fill="#f29b75"/><path d="m10 10v5l-2-1-2 1v-5z" fill="#fc6"/><path d="m10 10v3a3 3 0 0 1 -3-3z" fill="#ffde76"/></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1 @@
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><style>.st0{fill:#ffd180}.st1{fill:#bf3f49}.st2{fill:#d23b54}.st3{fill:#f7b957}.st4{fill:#edf4fa}.st5{fill:#2b2b37}.st6{fill:#b9c6de}.st7{fill:#d6e0eb}.st8{fill:#5c6979}.st9{fill:#393d48}</style><path class="st0" d="M63 7.2v33.5c0 1.2-.9 2.2-2.1 2.2H23V5h37.9C62.1 5 63 6 63 7.2z"/><path class="st1" d="M23 5v38H3c-1.1 0-2-.9-2-2V7c0-1.1.9-2 2-2h20z"/><path class="st2" d="M5 5H3c-1.1 0-2 .9-2 2v34c0 1.1.9 2 2 2h20V27.4C11.9 21.8 5 13.8 5 5z"/><path class="st3" d="M49.6 35.2c-.8-.1-1.7-.2-2.5-.4-.3 0-.7-.1-1-.2-3.6-.6-7.1-1.4-10.5-2.3-4.3-1.2-8.5-2.8-12.5-4.9V43H61c1.2 0 2.1-1 2.1-2.2V36c-4.6 0-9.1-.3-13.5-.8z"/><path class="st2" d="M56 24c0-1.1-2-1.9-2.3-2.9s1.1-2.7.6-3.6-2.7-.6-3.4-1.3c-.8-.7-.4-2.9-1.3-3.4s-2.6.8-3.6.6-1.9-2.4-3-2.4-1.9 2-2.9 2.3-2.7-1.1-3.6-.6-.6 2.7-1.3 3.4c-.7.8-2.9.4-3.4 1.3s.8 2.6.6 3.6-2.4 1.9-2.4 3 2 1.9 2.3 2.9-1.1 2.7-.6 3.6c.5.9 2.7.6 3.4 1.3.7.7.4 2.9 1.3 3.4s2.6-.8 3.6-.5 1.9 2.3 3 2.3 1.9-2 2.9-2.3 2.7 1.1 3.6.6.6-2.7 1.3-3.4 2.9-.4 3.4-1.3-.8-2.6-.5-3.6 2.3-1.9 2.3-3z"/><path class="st1" d="M54 24c0-.9-1.7-1.6-1.9-2.4s.9-2.3.5-3.1-2.3-.5-2.9-1.1-.4-2.4-1.1-2.9-2.2.7-3.1.5-1.6-2-2.5-2-1.6 1.7-2.4 1.9-2.3-.9-3.1-.5-.5 2.3-1.1 2.9-2.5.4-2.9 1.1.7 2.2.5 3.1-2 1.6-2 2.5 1.7 1.6 1.9 2.4-.9 2.3-.5 3.1 2.3.5 2.9 1.1.4 2.4 1.1 2.9 2.2-.7 3.1-.5 1.6 2 2.5 2 1.6-1.7 2.4-1.9 2.3.9 3.1.5.5-2.3 1.1-2.9 2.5-.4 2.9-1.1-.7-2.2-.5-3.1 2-1.6 2-2.5z"/><path class="st4" d="M13.5 23h-3C9.1 23 8 21.9 8 20.5S9.1 18 10.5 18H15c.6 0 1-.4 1-1s-.4-1-1-1h-2v-1c0-.6-.4-1-1-1s-1 .4-1 1v1h-.5C8 16 6 18 6 20.5S8 25 10.5 25h3c1.4 0 2.5 1.1 2.5 2.5S14.9 30 13.5 30H9c-.6 0-1 .4-1 1s.4 1 1 1h2v1c0 .6.4 1 1 1s1-.4 1-1v-1h.5c2.5 0 4.5-2 4.5-4.5S16 23 13.5 23zm36.2-5.7c-.4-.4-1-.4-1.4 0l-12 12c-.4.4-.4 1 0 1.4.4.4 1 .4 1.4 0l12-12c.4-.4.4-1 0-1.4zM46 26c-1.7 0-3 1.3-3 3s1.3 3 3 3 3-1.3 3-3-1.3-3-3-3zm0 4c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm-6-8c1.7 0 3-1.3 3-3s-1.3-3-3-3-3 1.3-3 3 1.3 3 3 3zm0-4c.6 0 1 .4 1 1s-.4 1-1 1-1-.4-1-1 .4-1 1-1z"/><path class="st5" d="M22.3 5h1.4v4h-1.4V5zm0 6h1.4v4h-1.4v-4zm0 6h1.4v4h-1.4v-4zm0 6h1.4v4h-1.4v-4zm0 6h1.4v4h-1.4v-4zm0 6h1.4v4h-1.4v-4zm0 6h1.4v2h-1.4v-2z"/><path class="st6" d="M26.7 43l-1.6 3.4-1.8-3.4h3.4zm-5.4 4.2l1.7 3.6-2 4.2c0-1.4-.7-2.6-1.8-3.4l2.1-4.4z"/><path class="st4" d="M23.3 43l1.8 3.4 2.5 4.8C26 51.8 25 53.3 25 55l-2-4.2-1.7-3.6L16 36l2-3 5.3 10z"/><path class="st7" d="M25.9 49c-.4.4-1.1.3-1.4-.1 0-.1-.1-.1-.1-.2l-7.2-14.4L16 36l5.3 11.2 1.7 3.6 2 4.2c0-1.7 1-3.2 2.6-3.7l-1.3-2.5c-.2 0-.3.1-.4.2z"/><path class="st8" d="M29 60c-2.8 0-5-2.2-5-5s2.2-5 5-5 5 2.2 5 5-2.2 5-5 5zm0-8c-1.7 0-3 1.3-3 3s1.3 3 3 3 3-1.3 3-3-1.3-3-3-3z"/><path class="st9" d="M17 60c-2.8 0-5-2.2-5-5s2.2-5 5-5 5 2.2 5 5-2.2 5-5 5zm0-8c-1.7 0-3 1.3-3 3s1.3 3 3 3 3-1.3 3-3-1.3-3-3-3z"/></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1 @@
<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><path d="m46.3 42 .7 2-35.6 12-4.9-14h30.5c1.1 0 2-.9 2-2v-1h3c0 1.6 1.3 3 2.9 3h.1z" fill="#e9edf5"/><path d="m63 24v18h-6v-3-13-2z" fill="#80dbff"/><path d="m60 24v18h-3v-3-13-2z" fill="#19cffc"/><path d="m39 33v-14h4l10 7h4v13h-4c0 1.6-1.3 3-2.9 3h-.1-5c-1.6 0-3-1.3-3-2.9v-.1h-6c-1.7 0-3-1.3-3-3 0-.7.3-1.5.8-2l.1-.1c.6-.6 1.3-.9 2.1-.9z" fill="#ffcdbe"/><path d="m42 30v-8-3h-3v3 8 3h3z" fill="#ffbeaa"/><path d="m36 36c0-.7.3-1.5.8-2l.1-.1c.6-.6 1.3-.9 2.1-.9h-3c-.8 0-1.6.3-2.1.9l-.1.1c-.5.5-.8 1.3-.8 2 0 1.7 1.3 3 3 3h3c-1.7 0-3-1.3-3-3z" fill="#ffbeaa"/><path d="m45 39h-3c0 1.6 1.3 3 2.9 3h.1 3c-1.6 0-3-1.3-3-3z" fill="#ffbeaa"/><path d="m39 39v1c0 1.1-.9 2-2 2h-15v-8h11.8c-.5.5-.8 1.3-.8 2 0 1.7 1.3 3 3 3z" fill="#e9edf5"/><path d="m39 30v3h-3c-.8 0-1.6.3-2.1.9l-.1.1h-11.8v-4z" fill="#d6475c"/><path d="m39 22v8h-17v-8h2z" fill="#e9edf5"/><path d="m39 19v3h-15v-6h13c1.1 0 2 .9 2 2z" fill="#9196aa"/><path d="m23 13c0-.6-.3-1.2-.8-1.6.7-2 2.6-3.4 4.8-3.4 4 0 4 1 4 3 0 1.1-.9 2-2 2 1.1.6 1.9 1.7 2 3h-8z" fill="#d6475c"/><path d="m24.2 11.4c.7-1.8 2.3-3.1 4.2-3.4-.4 0-.9 0-1.4 0-2.2 0-4.1 1.4-4.8 3.4.5.4.8 1 .8 1.6v3h2v-3c0-.6-.3-1.2-.8-1.6z" fill="#f25a6b"/><path d="m24 16v6h-2-4-2v-6h1 6z" fill="#d6475c"/><path d="m22.2 11.4c.5.4.8 1 .8 1.6v3h-6v-3c0-1.1.9-2 2-2h2c.4 0 .9.1 1.2.4z" fill="#ff808c"/><path d="m19.8 11.4c.3-.3.8-.4 1.2-.4h-2c-1.1 0-2 .9-2 2v3h2v-3c0-.6.3-1.2.8-1.6z" fill="#f25a6b"/><path d="m22 34v8h-4v-8-4-8h4v8z" fill="#f25a6b"/><path d="m18 34v8h-15c-1.1 0-2-.9-2-2v-6z" fill="#e9edf5"/><path d="m1 30h17v4h-17z" fill="#d6475c"/><path d="m1 30h3v4h-3z" fill="#ba4259"/><path d="m18 22v8h-17v-8h15z" fill="#e9edf5"/><path d="m17 13v3h-8c.1-1.3.9-2.4 2-3-1.1 0-2-.9-2-2 0-2 0-3 4-3 2.2 0 4.1 1.4 4.8 3.4-.5.4-.8 1-.8 1.6z" fill="#d6475c"/><path d="m13 13c-1.1 0-2-.9-2-2 0-1.7 0-2.7 2.6-2.9-.2-.1-.4-.1-.6-.1-4 0-4 1-4 3 0 1.1.9 2 2 2-1.1.6-1.9 1.7-2 3h2c.1-1.3.9-2.4 2-3z" fill="#f25a6b"/><path d="m16 16v6h-15v-4c0-1.1.9-2 2-2z" fill="#9196aa"/><path d="m4 40v-6h-3v6c0 1.1.9 2 2 2h3c-1.1 0-2-.9-2-2z" fill="#cdd2e1"/><path d="m1 22h3v8h-3z" fill="#cdd2e1"/><path d="m6 16h-3c-1.1 0-2 .9-2 2v4h3v-4c0-1.1.9-2 2-2z" fill="#636978"/><g fill="none" stroke="#404040" stroke-linejoin="round"><path d="m57 39h-4c0 1.6-1.3 3-2.9 3h-.1-5c-1.6 0-3-1.3-3-2.9v-.1h-6c-1.7 0-3-1.3-3-3s1.3-3 3-3h6l4-4"/><path d="m57 24h6v18h-6z"/><path d="m57 26h-4l-10-7h-4"/><path d="m39 33v-15c0-1.1-.9-2-2-2h-34c-1.1 0-2 .9-2 2v22c0 1.1.9 2 2 2h34c1.1 0 2-.9 2-2v-1"/><path d="m46.3 42 .7 2-35.6 12-4.9-14"/><path d="m1 22h38"/><path d="m16 16h8v6h-8z"/><path d="m18 22v20"/><path d="m22 22v20"/><path d="m1 30h17"/><path d="m22 30h17"/><path d="m1 34h17"/><path d="m22 34h12"/><path d="m17 16v-3c0-1.1.9-2 2-2h2c1.1 0 2 .9 2 2v3"/><path d="m22.2 11.4s.8-3.4 4.8-3.4 4 1 4 3c0 1.1-.9 2-2 2 1.1.6 1.9 1.7 2 3"/><path d="m17.8 11.4s-.8-3.4-4.8-3.4-4 1-4 3c0 1.1.9 2 2 2-1.1.6-1.9 1.7-2 3"/><path d="m23 13s4 0 4-2"/><path d="m17 13s-4 0-4-2"/><path d="m44 15v-6"/><path d="m56 20h-6"/><path d="m47 17.5 4.9-4.9"/></g></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1 @@
<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><path d="m9 52v-8h44c1.1 0 2-.9 2-2v-22h6c1.1 0 2 .9 2 2v30c0 1.1-.9 2-2 2h-50c-1.1 0-2-.9-2-2z" fill="#e9edf5"/><path d="m12 52v-8h-3v8c0 1.1.9 2 2 2h3c-1.1 0-2-.9-2-2zm46-10v-22h-3v22c0 1.1-.9 2-2 2h3c1.1 0 2-.9 2-2z" fill="#cdd2e1"/><path d="m14.5 34.5-5.5 5.5v-5h-4l4-4 2.4-2.4c.5.8 1.4 1.4 2.4 1.4-1 1.2-1 3 .1 4.1.2.2.4.3.6.4zm22.5.5h-4v5l-5.5-5.5c.2-.1.4-.3.6-.4 1.1-1.1 1.2-2.9.1-4.1 1-.1 1.8-.6 2.4-1.4l2.4 2.4z" fill="#f25a6b"/><path d="m1 23h12.2c.1.4.3.7.6 1-1.6.1-2.8 1.4-2.8 3 0 .6.1 1.1.4 1.6l-2.4 2.4h-8zm24 11.8v9.2h-8v-9.2c.4-.1.7-.3 1-.6 0 1.7 1.3 3 3 3s3-1.3 3-3c.3.3.6.5 1 .6zm3.8-11.8h26.2v8h-22l-2.4-2.4c.3-.5.4-1 .4-1.6 0-1.6-1.2-2.9-2.8-3 .3-.3.5-.6.6-1zm-3.8-13v9.2c-.4.1-.7.3-1 .6 0-1.7-1.3-3-3-3s-3 1.3-3 3c-.3-.3-.6-.5-1-.6v-9.2z" fill="#ff808c"/><circle cx="21" cy="27" fill="#f2f6fc" r="4"/><path d="m20 27c0-1.6 1-3.1 2.5-3.7-.5-.2-1-.3-1.5-.3-2.2 0-4 1.8-4 4s1.8 4 4 4c.5 0 1-.1 1.5-.3-1.5-.6-2.5-2.1-2.5-3.7z" fill="#dce1eb"/><path d="m11.4 28.6c-.3-.5-.4-1-.4-1.6 0-1.6 1.2-2.9 2.8-3-.3-.3-.5-.6-.6-1-.5-1.6.4-3.3 1.9-3.8.6-.2 1.3-.2 1.9 0 .4.1.7.3 1 .6 0-1.7 1.3-3 3-3s3 1.3 3 3c.3-.3.6-.5 1-.6 1.6-.5 3.3.4 3.8 1.9.2.6.2 1.3 0 1.9-.1.4-.3.7-.6 1 1.6.1 2.8 1.4 2.8 3 0 .6-.1 1.1-.4 1.6-.5.8-1.4 1.4-2.4 1.4 1 1.2 1 3-.1 4.1-.8.8-2 1.1-3.1.7-.4-.1-.7-.3-1-.6 0 1.7-1.3 3-3 3s-3-1.3-3-3c-.3.3-.6.5-1 .6-1.1.4-2.3.1-3.1-.7-1.1-1.1-1.2-2.9-.1-4.1-1-.1-1.9-.6-2.4-1.4zm13.6-1.6c0-2.2-1.8-4-4-4s-4 1.8-4 4 1.8 4 4 4 4-1.8 4-4z" fill="#d6475c"/><path d="m55 31v11c0 1.1-.9 2-2 2h-28v-9.2c.8.3 1.8.2 2.5-.3l5.5 5.5v-5h4l-4-4zm-38 3.8v9.2h-14c-1.1 0-2-.9-2-2v-11h8l-4 4h4v5l5.5-5.5c.7.5 1.7.6 2.5.3zm0-24.8v9.2c-1.6-.5-3.3.4-3.8 1.9-.2.6-.2 1.3 0 1.9h-12.2v-11c0-1.1.9-2 2-2zm38 13h-26.2c.5-1.6-.4-3.3-1.9-3.8-.6-.2-1.3-.2-1.9 0v-9.2h28c1.1 0 2 .9 2 2z" fill="#9196aa"/><path d="m1 23h3v8h-3z" fill="#f25a6b"/><path d="m1 31v11c0 1.1.9 2 2 2h1v-13zm3-21h-1c-1.1 0-2 .9-2 2v11h3z" fill="#636978"/><path d="m38 44h21v6h-21z" fill="#ff808c"/><path d="m38 44h4v6h-4z" fill="#d6475c"/><g fill="none" stroke="#404040" stroke-linejoin="round"><path d="m9 44v8c0 1.1.9 2 2 2h50c1.1 0 2-.9 2-2v-30c0-1.1-.9-2-2-2h-6"/><path d="m55 31v11c0 1.1-.9 2-2 2h-50c-1.1 0-2-.9-2-2v-30c0-1.1.9-2 2-2h50c1.1 0 2 .9 2 2z"/><path d="m17 19.2v-9.2"/><path d="m25 19.2v-9.2"/><path d="m17 44v-9.2"/><path d="m25 44v-9.2"/><path d="m28.8 23h26.2"/><path d="m33 31h22"/><path d="m1 23h12.2"/><path d="m1 31h8"/><circle cx="21" cy="27" r="4"/><path d="m27.5 34.5 5.5 5.5v-5h4l-4-4-2.4-2.4"/><path d="m14.5 34.5-5.5 5.5v-5h-4l4-4 2.4-2.4"/><path d="m57 44h2v6h-21v-4"/><path d="m35 50h-2"/><path d="m31 50h-19"/><path d="m30.6 28.6c.3-.5.4-1 .4-1.6 0-1.6-1.2-2.9-2.8-3 .3-.3.5-.6.6-1 .5-1.6-.4-3.3-1.9-3.8-.6-.2-1.3-.2-1.9 0-.4.1-.7.3-1 .6 0-1.7-1.3-3-3-3s-3 1.3-3 3c-.3-.3-.6-.5-1-.6-1.6-.5-3.3.4-3.8 1.9-.2.6-.2 1.3 0 1.9.1.4.3.7.6 1-1.6.1-2.8 1.4-2.8 3 0 .6.1 1.1.4 1.6.5.8 1.4 1.4 2.4 1.4-1 1.2-1 3 .1 4.1.8.8 2 1.1 3.1.7.4-.1.7-.3 1-.6 0 1.7 1.3 3 3 3s3-1.3 3-3c.3.3.6.5 1 .6 1.1.4 2.3.1 3.1-.7 1.1-1.1 1.2-2.9.1-4.1 1-.1 1.9-.6 2.4-1.4z"/></g></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1 @@
<svg enable-background="new 0 0 33.7 31.3" viewBox="0 0 33.7 31.3" xmlns="http://www.w3.org/2000/svg"><path d="m26.1 8.7c.3.6.5 1.3.5 2 .1 1.3-.6 2.4-1.7 3l-3.5-7.2c1.6-.8 3.7.3 4.7 2.2zm-19 13.8 1.5-.7 3.5 7.2c.1.2.2.4.2.7 0 .6-.4 1.2-1 1.4-.8.4-1.8 0-2.2-.8l-3.5-7.2v-.2c.5-.1 1-.2 1.5-.4z" fill="#d25065"/><path d="m4.4 13.2 4.2 8.6-1.5.7c-.5.2-1 .4-1.5.4-2.1.3-4.1-.8-5.1-2.7-.3-.6-.5-1.3-.5-2 0-1.9 1.2-3.6 2.9-4.3z" fill="#d23b54"/><path d="m24.8 13.7 3.2 6.5s-5.2-1.2-19.4 1.6l-4.2-8.6c12.1-9 13.7-13.2 13.7-13.2l3.2 6.5z" fill="#ffd180"/><path d="m7 18.5-1.5.7c-.5.2-1 .4-1.5.4-1.4.2-2.9-.3-4-1.2 0 .6.2 1.2.5 1.8.9 1.9 3 3 5.1 2.7.5-.1 1.1-.2 1.5-.4l1.5-.7z" fill="#bf3f49"/><path d="m7 18.5 1.6 3.3c14.2-2.8 19.4-1.6 19.4-1.6l-1.9-3.8c-4.1-.1-8.1.2-12.1.9-2.1.3-4.1-.7-5.1-2.6l-1.9-3.5c-.8.6-1.7 1.3-2.6 2z" fill="#f2b150"/><path d="m8.3 25.6c-.4-.9-.1-1.9.8-2.3 0 0 .1 0 .1-.1h.1l-.6-1.4-1.5.7c-.5.2-1 .4-1.5.4v.2l3.5 7.2c.4.7 1.2 1.1 2 .9zm15.4-16.8-1.2-2.5c-.4 0-.8.1-1.2.2l3.5 7.2c1.1-.6 1.8-1.7 1.7-3 0-.3 0-.6-.1-.9-1 .4-2.2 0-2.7-1z" fill="#bf3f49"/><path d="m9.5 13.2c-.4 0-.8-.2-1-.6-.4-.6-.2-1.3.3-1.7 1.2-.8 3.8-3 5.2-4.2.5-.4 1.3-.4 1.7.2.4.5.4 1.3-.2 1.7-2 1.6-4.2 3.5-5.4 4.3-.1.2-.4.3-.6.3zm9.8-8.3c0-.7-.5-1.2-1.2-1.2-.1 0-.2 0-.2 0-.1 0-.2 0-.2.1-.1 0-.1.1-.2.1 0 0-.1.1-.1.1l-.8.7c-.5.4-.6 1.2-.1 1.7.2.3.6.4.9.4s.6-.1.8-.3l.8-.7c.2-.2.3-.5.3-.9z" fill="#ffe0b3"/><path d="m27.2 8.2c-.5 0-.8-.3-.8-.8 0-.3.2-.6.4-.7l5.8-3.3c.4-.2.9-.1 1.1.3s.1.9-.3 1.1l-5.8 3.3c-.2.1-.3.1-.4.1zm-1.7-2.4c-.2 0-.4-.1-.5-.2-.3-.3-.4-.8-.1-1.1l3.5-4.1c.3-.3.8-.4 1.2-.1s.4.7.1 1.1l-3.5 4.1c-.2.2-.4.3-.7.3zm7.4 4.9h-4.9c-.5-.1-.8-.5-.7-.9 0-.4.3-.7.7-.7h4.9c.5.1.8.5.7.9 0 .4-.3.7-.7.7z" fill="#d23b54"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1 @@
<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><path d="m43 3v14c0 1.1-.9 2-2 2h-8v4l-4-4h-8c-1.1 0-2-.9-2-2v-14c0-1.1.9-2 2-2h20c1.1 0 2 .9 2 2z" fill="#ff808c"/><path d="m22 17v-14c0-1.1.9-2 2-2h-3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h3c-1.1 0-2-.9-2-2z" fill="#d6475c"/><path d="m32 19h-3l4 4v-3z" fill="#d6475c"/><path d="m33.3 60c1.1-.2 1.8-1.2 1.6-2.2 0 0 0 0 0-.1-.2-1.1-1.3-1.8-2.3-1.5-1.1.2-1.8 1.2-1.6 2.3.1 1 1.2 1.7 2.3 1.5zm-5.3-1c-.3-1.5.2-3.1 1.2-4.2.7-.8 1.7-1.3 2.8-1.5s2.2-.1 3.1.4c2.4 1.1 3.5 4 2.4 6.5-.7 1.5-2 2.5-3.6 2.8-2.7.4-5.3-1.3-5.9-4z" fill="#707789"/><path d="m34.8 57.7c.2 1.1-.5 2.1-1.5 2.3-1.1.2-2.1-.5-2.3-1.5-.2-1.1.5-2.1 1.6-2.3 1-.2 2 .5 2.2 1.5z" fill="#80dbff"/><path d="m29.2 54.8c-1 1.1-1.5 2.7-1.2 4.2l-2 .4c-.1 0-.3 0-.4 0-.9 0-1.6-.6-1.9-1.4v-.1c-.2-1.1.5-2.1 1.6-2.3l2.7-.6h.2z" fill="#dce1eb"/><path d="m61 51c0 1-.6 1.8-1.6 2l-21.6 4.1c-.3-1.5-1.3-2.8-2.7-3.5l20.6-3.9 2.9-.6c1.2-.1 2.2.7 2.4 1.9z" fill="#dce1eb"/><path d="m25.9 53.4c.2 1 1.1 1.7 2.1 1.5l-2.8.5c-1.1.2-1.8 1.2-1.6 2.3v.1h-2.6l-.8-5h5.5z" fill="#9196aa"/><path d="m20.2 53 .8 5h-4l-8-53h-4c-.5 0-1-.2-1.4-.6s-.6-.9-.6-1.4c0-1.1.9-2 2-2h7z" fill="#dce1eb"/><path d="m49.7 34.9 2.3 11.6-21.6 4.1-2.3-11.6z" fill="#f2f6fc"/><path d="m43.5 24.1 1.5 7.7-13.7 2.6-1.5-7.7z" fill="#ffde91"/><path d="m30.4 50.6 21.6-4.1-2.3-11.5-21.6 4zm-4.6 2.4-4.5-22.6c-.2-1.1.5-2.1 1.6-2.3l6.9-1.3 1.5 7.7 13.7-2.7-1.5-7.7 6.9-1.3c1.1-.2 2.1.5 2.3 1.5l4.6 23.1c.2 1.1-.5 2.1-1.6 2.3l-20.6 3.9c-1-.5-2.1-.6-3.1-.4-1.1.2-2 .7-2.8 1.5l-1 .2-.2.1c-1 .1-1.9-.6-2.1-1.6z" fill="#b2876d"/><path d="m43.5 24.1 1.5 7.7-13.7 2.6-1.5-7.7z" fill="#dce1eb"/><path d="m32.9 28.5-.5-2.3-2.7.5 1.5 7.7 13.8-2.6-.7-3.5-9.1 1.7c-1.1.3-2.1-.4-2.3-1.5z" fill="#cdd2e1"/><path d="m37.1 51.7c-1-.5-2.1-.6-3.1-.4-1.1.2-2 .7-2.8 1.5l-1 .2h-.2c-1 .1-1.9-.6-2.1-1.6l-.1-.4-4.5-22.6c0-.1 0-.2 0-.4l-.4.1c-1.1.2-1.8 1.2-1.6 2.3l4.5 22.6.1.5c.2 1 1.1 1.7 2.1 1.5h.2l1-.2c.7-.8 1.7-1.3 2.8-1.5s2.2-.1 3.1.4l20.6-3.9c.9-.2 1.6-1 1.6-1.9z" fill="#966857"/><path d="m31.6 41.2 15.7-3 .4 2-15.7 3z" fill="#bec3d2"/><path d="m46.1 42.4 2-.4.4 2-2 .4z" fill="#bec3d2"/><path d="m32.4 45 11.8-2.3.4 2-11.8 2.3z" fill="#bec3d2"/><ellipse cx="32.9" cy="58.1" fill="#dce1eb" rx="2" ry="2"/><g fill="none" stroke="#404040" stroke-linejoin="round"><path d="m35.1 53.7 23.6-4.5c1.1-.2 2.2.6 2.4 1.8 0 1-.6 1.8-1.6 2l-21.6 4.1"/><path d="m29.2 54.8-3.9.8c-1.1.2-1.8 1.2-1.6 2.3s1.3 1.8 2.3 1.5l2-.4"/><path d="m55.7 49.8c1.1-.2 1.8-1.2 1.6-2.3l-4.6-23.1c-.2-1.1-1.3-1.8-2.3-1.5l-27.5 5.2c-1.1.2-1.8 1.2-1.6 2.3l4.6 23.1c.2 1.1 1.3 1.8 2.3 1.5"/><path d="m43.5 24.1 1.5 7.7-13.7 2.6-1.5-7.7"/><path d="m30.4 50.6 21.6-4.1-2.3-11.5-21.6 4z"/><path d="m47.5 39.3-15.7 3"/><path d="m48.3 43.2-2 .4"/><path d="m44.3 43.9-11.8 2.2"/><path d="m24 58h-3l-9-57h-7c-1.1 0-2 .9-2 2s.9 2 2 2h4l8 53h4"/><path d="m20 53h6"/><path d="m43 3v14c0 1.1-.9 2-2 2h-8v4l-4-4h-8c-1.1 0-2-.9-2-2v-14c0-1.1.9-2 2-2h20c1.1 0 2 .9 2 2z"/><path d="m27 14 8-8"/><path d="m27 7h2"/><path d="m33 13h2"/><ellipse cx="32.9" cy="58.1" rx="5" ry="4.9"/></g></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 77.94 73.68" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(-1 0 0 1 278.59 0)" gradientUnits="userSpaceOnUse" x1="253.22" x2="264.2" y1="24.57" y2="65.52"><stop offset="0" stop-color="#c7a58d"/><stop offset="1" stop-color="#b89882"/></linearGradient><linearGradient id="b" gradientTransform="matrix(-1 0 0 1 278.59 0)" gradientUnits="userSpaceOnUse" x1="223.88" x2="212.68" y1="33.32" y2="72.37"><stop offset="0" stop-color="#aa8c79"/><stop offset="1" stop-color="#9d8472"/></linearGradient><linearGradient id="c" x1="255.88" x2="262.69" xlink:href="#a" y1="13.47" y2="38.88"/><linearGradient id="d" x1="220.87" x2="212.77" xlink:href="#b" y1="22.77" y2="53.01"/><linearGradient id="e" gradientTransform="matrix(-1 0 0 1 278.59 0)" gradientUnits="userSpaceOnUse" x1="239.88" x2="239.88" y1="37.16" y2="27.02"><stop offset="0" stop-color="#bb9c85"/><stop offset="1" stop-color="#f2d3bb"/></linearGradient><linearGradient id="f" gradientTransform="matrix(-1 0 0 1 278.59 0)" gradientUnits="userSpaceOnUse" x1="259.31" x2="263.18" y1="36.21" y2="29.5"><stop offset="0" stop-color="#e9c4aa"/><stop offset=".34" stop-color="#aa8c79"/><stop offset="1" stop-color="#9d8472"/></linearGradient><linearGradient id="g" x1="240.2" x2="239.07" xlink:href="#e" y1="74.17" y2="9.38"/><g fill-rule="evenodd"><path d="m38.97 46.6-37.7 13.54 37.7 13.53 37.7-13.53z" fill="#8f8f8f"/><path d="m38.97 1.22-37.7 13.54 37.7 13.54 37.7-13.54z" fill="#edecec"/><path d="m1.27 60.02v-45.26l37.7 13.54v45.26z" fill="url(#a)"/><path d="m76.67 60.02v-45.26l-37.7 13.54v45.26z" fill="url(#b)"/><path d="m1.27 24.14v-9.38l37.73 13.54v9.38z" fill="#b89983"/><path d="m76.67 24.14v-9.38l-37.67 13.54v9.38z" fill="#9d816e"/><path d="m76.67 14.96v-.2l-37.7 13.54-37.7-13.54v.2l37.7 13.75z" fill="#fff"/><path d="m38.97 0-38.97 14 38.97 13.99 38.97-13.99z" fill="#e9c4aa"/><path d="m0 23.01v-9.01l38.97 13.99v9.01z" fill="url(#c)"/><path d="m77.94 23.01v-9.01l-38.97 13.99v9.01z" fill="url(#d)"/><path d="m38.45 27.8.52.19v9.01l-.52-.18z" fill="url(#e)"/><path d="m77.94 14.21v-.21l-38.97 13.99-38.97-13.99v.21l38.97 14.2z" fill="#f2d3bb"/><path d="m24.1 35.79-8.72-3.11a1.75 1.75 0 0 0 -2.38 1.86 4.38 4.38 0 0 0 2.42 3.81l8.72 3.11c1.33.47 2.42-.59 2.42-2.09a4 4 0 0 0 -2.46-3.58z" fill="url(#f)"/><path d="m24.1 35.79-8.72-3.11c-1.15-.5-2 .47-2 1.74a4 4 0 0 0 2.46 3.58l8.72 3.11c1.15.49 2-.48 2-1.75a4 4 0 0 0 -2.46-3.57z" fill="#5f5243"/><path d="m38.46 37.52.51.18v35.86l-.51-.18z" fill="url(#g)"/></g></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><defs><style>.a{fill:#db5669}.b{fill:#f26674}.c{fill:#c4455e}.d{fill:#ffde76}.e{fill:#edebf2}</style></defs><path class="a" d="M45.93 26.39a3.2 3.2 0 0 0-.76 3.79 3.21 3.21 0 0 1-1.83 4.42 3.19 3.19 0 0 0-2.15 3v.39a3.21 3.21 0 0 1-3.4 3.2 3.19 3.19 0 0 0-3.21 2.14 3.2 3.2 0 0 1-4.42 1.83 3.2 3.2 0 0 0-3.79.76 3.2 3.2 0 0 1-4.78 0 3.2 3.2 0 0 0-3.79-.76 3.2 3.2 0 0 1-4.42-1.83 3.18 3.18 0 0 0-3.21-2.14 3.2 3.2 0 0 1-3.37-3.38 3.19 3.19 0 0 0-2.14-3.21 3.2 3.2 0 0 1-1.83-4.42 3.2 3.2 0 0 0-.76-3.79 3.2 3.2 0 0 1 0-4.78 3.2 3.2 0 0 0 .76-3.79 3.2 3.2 0 0 1 1.83-4.42 3.18 3.18 0 0 0 2.14-3.21 3.2 3.2 0 0 1 3.3-3.39h.29a3.19 3.19 0 0 0 3-2.15 3.21 3.21 0 0 1 4.42-1.83 3.2 3.2 0 0 0 3.79-.76 3.2 3.2 0 0 1 4.78 0 3.21 3.21 0 0 0 3.79.76 3.2 3.2 0 0 1 4.43 1.84 3.19 3.19 0 0 0 3 2.15h.39a3.21 3.21 0 0 1 3.2 3.4 3.19 3.19 0 0 0 2.14 3.21 3.19 3.19 0 0 1 2.15 3c0 1.29-.64 1.52-.64 2.79C44.85 21.68 47 21.53 47 24a3.19 3.19 0 0 1-1.07 2.39z"/><path class="b" d="M45.93 26.39a3.2 3.2 0 0 0-.76 3.79 3.12 3.12 0 0 1 .18 2.3c0 .1-.76 1.28-.82 1.38a3.08 3.08 0 0 1-1.19.74 3.19 3.19 0 0 0-2.15 3v.29C27.32 51.18 4 41.37 4 22a21.9 21.9 0 0 1 6.1-15.2 3.2 3.2 0 0 0 3.3-2.14c.38-1.13 1-1.39 2.11-2a2.89 2.89 0 0 1 .91-.14c1.29 0 1.52.64 2.79.64C21.68 3.15 21.53 1 24 1a3.19 3.19 0 0 1 2.39 1.07 3.21 3.21 0 0 0 3.79.76 3.2 3.2 0 0 1 4.42 1.83 3.18 3.18 0 0 0 3.21 2.14 3.2 3.2 0 0 1 3.39 3.39 3.19 3.19 0 0 0 2.14 3.21 3.2 3.2 0 0 1 1.83 4.42 3.2 3.2 0 0 0 .76 3.79 3.2 3.2 0 0 1 0 4.78z"/><path class="c" d="M41 24a17 17 0 0 1-17 17C8.17 41 1 21.21 13 11c10.87-9.18 28-1.64 28 13z"/><path class="a" d="M41 24a16.91 16.91 0 0 1-4 11 16.91 16.91 0 0 1-11 4C11.38 39 3.81 21.88 13 11c10.87-9.18 28-1.64 28 13z"/><path class="d" d="M31.77 16.23a11 11 0 0 0-15.54 0 1 1 0 0 1-1.42-1.42 13 13 0 0 1 18.38 0 1 1 0 0 1-1.42 1.42zM14.81 33.19a1 1 0 0 1 1.42-1.42 11 11 0 0 0 15.54 0 1 1 0 0 1 1.42 1.42 13 13 0 0 1-18.38 0z"/><path class="e" d="M13 21h2a1 1 0 0 0 0-2h-2a3 3 0 0 0 0 6 1 1 0 0 1 0 2h-2a1 1 0 0 0 0 2h2a3 3 0 0 0 0-6 1 1 0 0 1 0-2zm8.94-1.35a1 1 0 0 0-1.88 0l-3 8a1 1 0 0 0 1.88.7l.5-1.35h3.12l.5 1.35a1 1 0 0 0 1.88-.7zM20.19 25l.81-2.15.81 2.15zM30 27h-2v-7a1 1 0 0 0-2 0v8a1 1 0 0 0 1 1h3a1 1 0 0 0 0-2zm7-2a1 1 0 0 0 0-2h-3v-2h3a1 1 0 0 0 0-2h-4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h4a1 1 0 0 0 0-2h-3v-2z"/></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><defs><style>.a{fill:#6fabe6}.b{fill:#82bcf4}.c{fill:#5b9ad8}.d{fill:#dad7e5}.e{fill:#edebf2}.f{fill:#db5669}.g{fill:#f26674}.h{fill:#ffde76}</style></defs><path class="a" d="M1 5H47V15H1z"/><path class="b" d="M47 5v8H7a4 4 0 0 1-4-4V5z"/><path class="c" d="M10 10a2 2 0 1 1-2.82-1.82A2 2 0 0 1 10 10zm4 2a2 2 0 1 1 2-2 2 2 0 0 1-2 2zm0-2zm26 2a2 2 0 1 1 2-2 2 2 0 0 1-2 2zm0-2zm-6 2a2 2 0 1 1 2-2 2 2 0 0 1-2 2zm0-2z"/><path class="d" d="M1 15H47V47H1z"/><path class="e" d="M47 15v30H11a8 8 0 0 1-8-8V15z"/><path class="f" d="M25.72 19.76a2.32 2.32 0 0 0 2.42.65 2.32 2.32 0 0 1 3 1.71 2.29 2.29 0 0 0 1.77 1.77 2.32 2.32 0 0 1 1.71 3 2.33 2.33 0 0 0 .65 2.42 2.33 2.33 0 0 1 0 3.44 2.32 2.32 0 0 0-.65 2.42 2.32 2.32 0 0 1-1.71 3 2.29 2.29 0 0 0-1.77 1.77 2.32 2.32 0 0 1-3 1.71 2.33 2.33 0 0 0-2.42.65 2.33 2.33 0 0 1-3.44 0 2.32 2.32 0 0 0-2.42-.65 2.32 2.32 0 0 1-3-1.71 2.29 2.29 0 0 0-1.77-1.77 2.32 2.32 0 0 1-1.71-3 2.33 2.33 0 0 0-.65-2.42 2.33 2.33 0 0 1 0-3.44 2.32 2.32 0 0 0 .65-2.42 2.32 2.32 0 0 1 1.71-3 2.29 2.29 0 0 0 1.77-1.77 2.32 2.32 0 0 1 3-1.71 2.33 2.33 0 0 0 2.42-.65 2.33 2.33 0 0 1 3.44 0z"/><path class="g" d="M34.59 35.14a2.33 2.33 0 0 1-1.71 3 2.31 2.31 0 0 0-1.77 1.75c-10.14 4.77-20.74-5.84-16-16a2.31 2.31 0 0 0 1.75-1.77 2.33 2.33 0 0 1 2.26-1.82c.66 0 .79.22 1.41.22 1.78 0 1.72-1.52 3.47-1.52a2.34 2.34 0 0 1 1.72.76 2.33 2.33 0 0 0 2.42.65 2.33 2.33 0 0 1 3 1.71 2.3 2.3 0 0 0 1.77 1.77 2.33 2.33 0 0 1 1.82 2.26c0 .66-.22.79-.22 1.41C34.48 29.32 36 29.24 36 31c0 1.92-2.08 1.93-1.41 4.14z"/><path class="h" d="M19 37a1 1 0 0 1-.71-1.71l10-10a1 1 0 0 1 1.42 1.42C18.88 37.53 19.6 37 19 37z"/><path class="a" d="M9.82 10.82a2 2 0 0 1-2.64-2.64 2 2 0 0 1 2.64 2.64zm6 0a2 2 0 0 1-2.64-2.64 2 2 0 0 1 2.64 2.64zm20 0a2 2 0 0 1-2.64-2.64 2 2 0 0 1 2.64 2.64zm6 0a2 2 0 0 1-2.64-2.64 2 2 0 0 1 2.64 2.64z"/><path class="d" d="M7 9V1a1 1 0 0 1 2 0v8a1 1 0 0 1-2 0zm6 0V1a1 1 0 0 1 2 0v8a1 1 0 0 1-2 0zm26 0V1a1 1 0 0 1 2 0v8a1 1 0 0 1-2 0zm-6 0V1a1 1 0 0 1 2 0v8a1 1 0 0 1-2 0z"/><path class="h" d="M21 30a3 3 0 1 0-3-3 3 3 0 0 0 3 3zm0-4a1 1 0 0 1 0 2 1 1 0 0 1 0-2zm6 6a3 3 0 1 0 3 3 3 3 0 0 0-3-3zm0 4a1 1 0 0 1 0-2 1 1 0 0 1 0 2z"/></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1 @@
<svg enable-background="new 0 0 64 64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><path d="m42 55h-39c-1.1 0-2-.9-2-2v-26c0-1.1.9-2 2-2h39z" fill="#ffd180"/><path d="m30.4 14.8-20.2-5.7c-.9-.3-1.9.2-2.2 1.1l-4.8 14.8h39.3l2-6.2z" fill="#f2b150"/><path d="m63 24.1-18.5-5.2-2 6.2h20.5z" fill="#d23b54"/><circle cx="27" cy="47" fill="#ff6161" r="1"/><circle cx="23" cy="41" fill="#ff6161" r="1"/><path d="m63 25h-21v30h21v-3l-2-3 2-3-2-3 2-3-2-3 2-3-2-3 2-3z" fill="#f17283"/><path d="m3 25c-1.1 0-2 .9-2 2v26c0 1.1.9 2 2 2h39v-7.3c-22.7-3.3-39-12.2-39-22.7z" fill="#f7b957"/><path d="m42 47.7v7.3h21v-3l-2-3c-6.4 0-12.7-.4-19-1.3z" fill="#d23b54"/><path d="m63 25h-2v3l-2 3 2 3-2 3 2 3-2 3 2 3-2 3 2 3v3h2v-3l-2-3 2-3-2-3 2-3-2-3 2-3-2-3 2-3z" fill="#d23b54"/><g fill="#2b2b37"><path d="m41.5 25h1v2h-1z"/><path d="m41.5 29h1v2h-1z"/><path d="m41.5 33h1v2h-1z"/><path d="m41.5 37h1v2h-1z"/><path d="m41.5 41h1v2h-1z"/><path d="m41.5 45h1v2h-1z"/><path d="m41.5 49h1v2h-1z"/><path d="m41.5 53h1v2h-1z"/></g><path d="m53.5 39h-3c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5h4.5c.6 0 1-.4 1-1s-.4-1-1-1h-2v-1c0-.6-.4-1-1-1s-1 .4-1 1v1h-.5c-2.5 0-4.5 2-4.5 4.5s2 4.5 4.5 4.5h3c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5h-4.5c-.6 0-1 .4-1 1s.4 1 1 1h2v1c0 .6.4 1 1 1s1-.4 1-1v-1h.5c2.5 0 4.5-2 4.5-4.5s-2-4.5-4.5-4.5z" fill="#fbfbfb"/><path d="m29 27.5h-3c-.2 0-.4.2-.5.4l-.6 2.6h-15.9c-.1 0-.3.1-.4.2s-.1.3-.1.4l2 10c0 .2.3.4.5.4h13c.8 0 1.5.7 1.5 1.5s-.7 1.5-1.5 1.5h-14c-.3 0-.5.2-.5.5v.6c-.8.3-1.2 1.1-.9 1.9s1.1 1.2 1.9.9 1.2-1.1.9-1.9c-.2-.4-.5-.8-.9-.9v-.1h12v.1c-.8.3-1.2 1.1-.9 1.9s1.1 1.2 1.9.9 1.2-1.1.9-1.9c-.2-.4-.5-.8-.9-.9v-.1h.5c1.4 0 2.5-1.1 2.5-2.5s-1.1-2.5-2.5-2.5h-.4l2.8-12h2.6c.3 0 .5-.2.5-.5s-.2-.5-.5-.5zm-19 20c-.3 0-.5-.2-.5-.5s.2-.5.5-.5.5.2.5.5-.2.5-.5.5zm13 0c-.3 0-.5-.2-.5-.5s.2-.5.5-.5.5.2.5.5-.2.5-.5.5zm-13.4-16h15.1l-.5 2h-12.2c-.3 0-.5.2-.5.5s.2.5.5.5h12l-.7 3h-11.3c-.3 0-.5.2-.5.5s.2.5.5.5h11.1l-.5 2h-11.2z" fill="#2b2b37"/><path d="m25 36c4.4 0 8 3.6 8 8s-3.6 8-8 8-8-3.6-8-8c0-.8.1-1.6.4-2.4.9-3.1 3.6-5.3 6.8-5.6z" fill="#2b2b37"/><circle cx="25" cy="44" fill="#ff6161" r="7"/><circle cx="27" cy="47" fill="#fbfbfb" r="1"/><circle cx="23" cy="41" fill="#fbfbfb" r="1"/><path d="m21 48.5c-.1 0-.3-.1-.4-.2-.2-.2-.2-.5 0-.7l8-8c.2-.2.5-.2.7 0s.2.5 0 .7l-8 8c0 .1-.2.2-.3.2z" fill="#fbfbfb"/><path d="m3.9 23-.6 2h9.7 12 1 16 .6l.6-2z" fill="#e69e2d"/><path d="m43.2 23-.6 2h20.4v-.9l-3.8-1.1z" fill="#c23b54"/><path d="m42.5 23.7.5-1.7 1 .3-.6 1.7z" fill="#222430"/><path d="m43.5 20.3.5-1.7 1 .3-.5 1.7z" fill="#222430"/><path d="m32.5 17.6-2.6-.8c-.2-.1-.4 0-.6.2l-1.2 2-14-4c-.1 0-.3 0-.4.1s-.2.2-.2.4l-1 9.5h1l.9-8.8 13.1 3.7-.9 1.4-10.7-3c-.3-.1-.6.1-.6.4-.1.3.1.6.4.6l10.4 3-1.2 1.8-10.1-2.6c-.3-.1-.6.1-.6.4-.1.3.1.6.4.6l9.4 2.5h1.6l4.3-7.1 2.3.6c.3.1.6-.1.6-.4s0-.5-.3-.5z" fill="#222430"/></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,44 @@
/**
* WooCommerce Smart Coupons JavaScript
*
* @package WooCommerce Smart Coupons/Assets/JS
*/
jQuery(
function(){
tinymce.create(
'tinymce.plugins.smart_coupons_shortcode_plugin',
{
init : function(ed, url) {
var assetsUrl = url.substr( 0, url.lastIndexOf( "/js" ) );
// Register command for when button is clicked.
ed.addCommand(
'smart_coupons_insert_shortcode',
function() {
ed.windowManager.open(
{
id : 'sc_coupons_attributes',
width : "auto",
height : "auto",
wpDialog : true
},
{
plugin_url : url // Plugin absolute URL.
}
);
}
);
// Register buttons - trigger above command when clicked.
ed.addButton( 'sc_shortcode_button', {title : 'Insert Smart Coupons shortcode', cmd : 'smart_coupons_insert_shortcode', classes: 'smart-coupon-shortcode btn' } );
},
}
);
// Register our TinyMCE plugin.
// first parameter is the button ID1.
// second parameter must match the first parameter of the tinymce.create() function above.
tinymce.PluginManager.add( 'sc_shortcode_button', tinymce.plugins.smart_coupons_shortcode_plugin );
}
);

View File

@@ -0,0 +1,56 @@
<?php
/**
* Smart Coupons Block
*
* @author StoreApps
* @since 8.7.0
* @version 1.1.0
*
* @package woocommerce-smart-coupons/blocks/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
add_action(
'woocommerce_blocks_loaded',
function() {
require_once __DIR__ . '/class-wc-sc-blocks-integration.php';
add_action(
'woocommerce_blocks_cart_block_registration',
function( $integration_registry ) {
if ( is_object( $integration_registry ) && is_callable( array( $integration_registry, 'register' ) ) && class_exists( 'WC_SC_Blocks_Integration' ) ) {
$integration_registry->register( WC_SC_Blocks_Integration::get_instance() );
}
}
);
add_action(
'woocommerce_blocks_checkout_block_registration',
function( $integration_registry ) {
if ( is_object( $integration_registry ) && is_callable( array( $integration_registry, 'register' ) ) && class_exists( 'WC_SC_Blocks_Integration' ) ) {
$integration_registry->register( WC_SC_Blocks_Integration::get_instance() );
}
}
);
}
);
/**
* Registers the slug as a block category with WordPress.
*
* @param array $categories List of existing categories.
* @return array
*/
function register_woocommerce_smart_coupons_block_category( $categories ) {
return array_merge(
$categories,
array(
array(
'slug' => 'woocommerce-smart-coupons',
'title' => _x( 'WooCommerce Smart Coupons', 'Block editor', 'woocommerce-smart-coupons' ),
),
)
);
}
add_action( 'block_categories_all', 'register_woocommerce_smart_coupons_block_category', 10, 2 );

View File

@@ -0,0 +1 @@
<?php return array('dependencies' => array('wp-plugins'), 'version' => 'd5cb900dccd24bde5039');

View File

@@ -0,0 +1 @@
(()=>{"use strict";(0,window.wp.plugins.registerPlugin)("woocommerce-smart-coupons",{render:()=>{}})})();

View File

@@ -0,0 +1,29 @@
{
"apiVersion": 2,
"name": "woocommerce-smart-coupons/available-coupons",
"version": "1.0.0",
"title": "Available coupons",
"category": "woocommerce-smart-coupons",
"description": "Displays available coupons.",
"supports": {
"html": false,
"align": false,
"multiple": false,
"reusable": false
},
"attributes": {
"lock": {
"type": "object",
"default": {
"remove": true,
"move": true
}
}
},
"parent": [
"woocommerce/checkout-contact-information-block",
"woocommerce/cart-items-block"
],
"textdomain": "woocommerce-smart-coupons",
"editorStyle": "file:../../../build/style-woocommerce-smart-coupons-available-coupons-block.css"
}

View File

@@ -0,0 +1,28 @@
{
"apiVersion": 2,
"name": "woocommerce-smart-coupons/send-coupon-form",
"version": "1.0.0",
"title": "Send coupon form",
"category": "woocommerce-smart-coupons",
"description": "Displays Send coupon form.",
"supports": {
"html": false,
"align": false,
"multiple": false,
"reusable": false
},
"parent": [
"woocommerce/checkout-contact-information-block"
],
"attributes": {
"lock": {
"type": "object",
"default": {
"remove": true,
"move": true
}
}
},
"textdomain": "woocommerce-smart-coupons",
"editorStyle": "file:../../../build/style-woocommerce-smart-coupons-send-coupon-form-block.css"
}

View File

@@ -0,0 +1 @@
.wp-block-woocommerce-smart-coupons-available-coupons{margin:1.25em 0;padding-top:.25em;padding-bottom:.25em;display:flex;align-items:flex-start}.wp-block-woocommerce-smart-coupons-available-coupons .block-editor-rich-text__editable{vertical-align:middle;line-height:1.5em}.wp-block-woocommerce-smart-coupons-available-coupons .wc-block-components-checkbox{margin-right:1em;margin-top:0}.editor-styles-wrapper .wp-block-woocommerce-smart-coupons-available-coupons .wc-block-components-checkbox{margin-right:0;margin-top:0}

View File

@@ -0,0 +1 @@
.wp-block-woocommerce-smart-coupons-send-coupon-form{margin:1.25em 0;padding-top:.25em;padding-bottom:.25em;color:inherit}.wp-block-woocommerce-smart-coupons-send-coupon-form h2,.wp-block-woocommerce-smart-coupons-send-coupon-form p,.wp-block-woocommerce-smart-coupons-send-coupon-form span,.wp-block-woocommerce-smart-coupons-send-coupon-form hr{color:inherit}.wp-block-woocommerce-smart-coupons-send-coupon-form p{margin:.5em 0}.wp-block-woocommerce-smart-coupons-send-coupon-form .components-radio-control{margin:.3em 0}.wp-block-woocommerce-smart-coupons-send-coupon-form .components-radio-control .components-radio-control__input{margin:.3em .3em .3em 0}.wp-block-woocommerce-smart-coupons-send-coupon-form span.components-text{margin-right:1em;line-height:3em}.wp-block-woocommerce-smart-coupons-send-coupon-form input.components-text-control__input{margin:.25em 0;background-color:inherit;border-color:inherit;height:4em !important;border-radius:4px}.wp-block-woocommerce-smart-coupons-send-coupon-form input.components-text-control__input:focus{background-color:inherit}.wp-block-woocommerce-smart-coupons-send-coupon-form textarea.components-textarea-control__input{margin:1em 0;background-color:inherit;border-color:inherit;border-radius:4px}.wp-block-woocommerce-smart-coupons-send-coupon-form textarea.components-textarea-control__input:focus{background-color:inherit}.wp-block-woocommerce-smart-coupons-send-coupon-form .components-datetime{width:50%;margin:.8em 0}.wp-block-woocommerce-smart-coupons-send-coupon-form .components-datetime .components-datetime__time-legend{margin-left:0}.wp-block-woocommerce-smart-coupons-send-coupon-form .components-datetime fieldset{background-color:inherit}

View File

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'wc-blocks-checkout'), 'version' => '1874eacfda75be94d1cf');

View File

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '7f8ac7c7693031291c67');

View File

@@ -0,0 +1 @@
<?php return array('dependencies' => array('lodash', 'react', 'wc-blocks-checkout', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '8ef4155dcf03f3b7fa6a');

View File

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '8888e98d7175c71ca97b');

View File

@@ -0,0 +1,675 @@
<?php
/**
* Smart Coupons Block integration
*
* @author StoreApps
* @since 8.7.0
* @version 1.1.0
*
* @package woocommerce-smart-coupons/blocks/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
use Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface;
if ( class_exists( 'WC_SC_Blocks_Integration' ) || ! interface_exists( 'Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface' ) ) {
return;
}
/**
* Class for integrating with WooCommerce Blocks
*/
class WC_SC_Blocks_Integration implements IntegrationInterface {
/**
* Variable to hold instance of WC_SC_Blocks_Integration
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'wp_loaded', array( $this, 'load_script_data_for_blocks' ) );
}
/**
* Get single instance of WC_SC_Blocks_Integration
*
* @return WC_SC_Blocks_Integration Singleton object of WC_SC_Blocks_Integration
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* The name of the integration.
*
* @return string
*/
public function get_name() {
return 'woocommerce-smart-coupons';
}
/**
* When called invokes any initialization/setup for the integration.
*/
public function initialize() {
$this->register_available_coupons_integration();
$this->register_send_coupon_form_integration();
$this->register_main_integration();
}
/**
* Register available coupons integration
*/
public function register_available_coupons_integration() {
$this->register_available_coupons_block_frontend_scripts();
$this->register_available_coupons_block_editor_scripts();
$this->register_available_coupons_block_editor_styles();
}
/**
* Register send coupon for integration
*/
public function register_send_coupon_form_integration() {
require_once __DIR__ . '/class-wc-sc-extend-store-endpoint.php';
$this->register_send_coupon_form_block_frontend_scripts();
$this->register_send_coupon_form_block_editor_scripts();
$this->register_send_coupon_form_block_editor_styles();
$this->extend_store_api();
}
/**
* Register available coupons block frontend scripts
*/
public function register_available_coupons_block_frontend_scripts() {
$script_path = '/blocks/build/woocommerce-smart-coupons-available-coupons-block-frontend.js';
$script_url = $this->get_plugin_directory_url( $script_path );
$script_asset_path = $this->get_plugin_directory( '/blocks/build/woocommerce-smart-coupons-available-coupons-block-frontend.asset.php' );
$script_asset = file_exists( $script_asset_path )
? require $script_asset_path
: array(
'dependencies' => array( 'wp-i18n' ),
'version' => $this->get_file_version( $script_asset_path ),
);
wp_register_script(
'woocommerce-smart-coupons-available-coupons-block-frontend',
$script_url,
$script_asset['dependencies'],
$script_asset['version'],
true
);
wp_set_script_translations(
'woocommerce-smart-coupons-available-coupons-block-frontend', // script handle.
'woocommerce-smart-coupons', // text domain.
$this->get_plugin_directory( '/languages' )
);
}
/**
* Register available coupons block editor scripts
*/
public function register_available_coupons_block_editor_scripts() {
$script_path = '/blocks/build/woocommerce-smart-coupons-available-coupons-block.js';
$script_url = $this->get_plugin_directory_url( $script_path );
$script_asset_path = $this->get_plugin_directory( '/blocks/build/woocommerce-smart-coupons-available-coupons-block.asset.php' );
$script_asset = file_exists( $script_asset_path )
? require $script_asset_path
: array(
'dependencies' => array( 'wp-i18n' ),
'version' => $this->get_file_version( $script_asset_path ),
);
wp_register_script(
'woocommerce-smart-coupons-available-coupons-block-editor',
$script_url,
$script_asset['dependencies'],
$script_asset['version'],
true
);
wp_set_script_translations(
'woocommerce-smart-coupons-available-coupons-block-editor', // script handle.
'woocommerce-smart-coupons', // text domain.
$this->get_plugin_directory( '/languages' )
);
}
/**
* Register available coupons block editor styles
*/
public function register_available_coupons_block_editor_styles() {
$style_path = '/blocks/build/style-woocommerce-smart-coupons-available-coupons-block.css';
$style_url = $this->get_plugin_directory_url( $style_path );
wp_enqueue_style(
'woocommerce-smart-coupons-available-coupons-block',
$style_url,
array(),
$this->get_file_version( $style_path )
);
}
/**
* Register send coupon form block frontend scripts
*/
public function register_send_coupon_form_block_frontend_scripts() {
$script_path = '/blocks/build/woocommerce-smart-coupons-send-coupon-form-block-frontend.js';
$script_url = $this->get_plugin_directory_url( $script_path );
$script_asset_path = $this->get_plugin_directory( '/blocks/build/woocommerce-smart-coupons-send-coupon-form-block-frontend.asset.php' );
$script_asset = file_exists( $script_asset_path )
? require $script_asset_path
: array(
'dependencies' => array( 'wp-i18n' ),
'version' => $this->get_file_version( $script_asset_path ),
);
wp_register_script(
'woocommerce-smart-coupons-send-coupon-form-block-frontend',
$script_url,
$script_asset['dependencies'],
$script_asset['version'],
true
);
wp_set_script_translations(
'woocommerce-smart-coupons-send-coupon-form-block-frontend', // script handle.
'woocommerce-smart-coupons', // text domain.
$this->get_plugin_directory( '/languages' )
);
}
/**
* Register send coupon form block editor scripts
*/
public function register_send_coupon_form_block_editor_scripts() {
$script_path = '/blocks/build/woocommerce-smart-coupons-send-coupon-form-block.js';
$script_url = $this->get_plugin_directory_url( $script_path );
$script_asset_path = $this->get_plugin_directory( '/blocks/build/woocommerce-smart-coupons-send-coupon-form-block.asset.php' );
$script_asset = file_exists( $script_asset_path )
? require $script_asset_path
: array(
'dependencies' => array( 'wp-i18n' ),
'version' => $this->get_file_version( $script_asset_path ),
);
wp_register_script(
'woocommerce-smart-coupons-send-coupon-form-block-editor',
$script_url,
$script_asset['dependencies'],
$script_asset['version'],
true
);
wp_set_script_translations(
'woocommerce-smart-coupons-send-coupon-form-block-editor', // script handle.
'woocommerce-smart-coupons', // text domain.
$this->get_plugin_directory( '/languages' )
);
}
/**
* Register send coupon form block editor styles
*/
public function register_send_coupon_form_block_editor_styles() {
$style_path = '/blocks/build/style-woocommerce-smart-coupons-send-coupon-form-block.css';
$style_url = $this->get_plugin_directory_url( $style_path );
wp_enqueue_style(
'woocommerce-smart-coupons-send-coupon-form-block',
$style_url,
array( 'wp-components' ),
$this->get_file_version( $style_path )
);
}
/**
* Extends the cart schema to include the shipping-workshop value.
*/
private function extend_store_api() {
WC_SC_Extend_Store_Endpoint::init();
}
/**
* Save data from Send coupon form
*/
private function save_send_coupon_data() {
/**
* 📝 Write a hook, using the `woocommerce_store_api_checkout_update_order_from_request` action
* that will update the order metadata with the shipping-workshop alternate shipping instruction.
*
* The documentation for this hook is at: https://github.com/woocommerce/woocommerce-blocks/blob/b73fbcacb68cabfafd7c3e7557cf962483451dc1/docs/third-party-developers/extensibility/hooks/actions.md#woocommerce_store_api_checkout_update_order_from_request
*/
add_action(
'woocommerce_store_api_checkout_update_order_from_request',
function( \WC_Order $order, \WP_REST_Request $request ) {
$send_coupon_data = $request['extensions']['woocommerce-smart-coupons'];
if ( ! empty( $send_coupon_data['is_gift'] ) ) {
$order->update_meta_data( 'is_gift', $send_coupon_data['is_gift'] );
}
if ( ! empty( $send_coupon_data['wc_sc_schedule_gift_sending'] ) ) {
$order->update_meta_data( 'wc_sc_schedule_gift_sending', $send_coupon_data['wc_sc_schedule_gift_sending'] );
}
if ( ! empty( $send_coupon_data['gift_receiver_email'] ) ) {
$gift_receiver_email = array();
if ( ! is_scalar( $send_coupon_data['gift_receiver_email'] ) ) {
foreach ( $send_coupon_data['gift_receiver_email'] as $key => $email ) {
list( $coupon_id, $index ) = explode( '_', $key );
$coupon_id = ( ! empty( $coupon_id ) ) ? intval( $coupon_id ) : 0;
$index = ( ! empty( $index ) ) ? intval( $index ) : 0;
if ( empty( $gift_receiver_email[ $coupon_id ] ) || ! is_array( $gift_receiver_email[ $coupon_id ] ) ) {
$gift_receiver_email[ $coupon_id ] = array();
}
$gift_receiver_email[ $coupon_id ][ $index ] = $email;
}
}
if ( ! empty( $gift_receiver_email ) ) {
$order->update_meta_data( 'gift_receiver_email', $gift_receiver_email );
}
}
if ( ! empty( $send_coupon_data['gift_sending_timestamp'] ) ) {
$gift_sending_timestamp = array();
if ( ! is_scalar( $send_coupon_data['gift_sending_timestamp'] ) ) {
foreach ( $send_coupon_data['gift_sending_timestamp'] as $key => $timestamp ) {
list( $coupon_id, $index ) = explode( '_', $key );
$coupon_id = ( ! empty( $coupon_id ) ) ? intval( $coupon_id ) : 0;
$index = ( ! empty( $index ) ) ? intval( $index ) : 0;
if ( empty( $gift_sending_timestamp[ $coupon_id ] ) || ! is_array( $gift_sending_timestamp[ $coupon_id ] ) ) {
$gift_sending_timestamp[ $coupon_id ] = array();
}
$gift_sending_timestamp[ $coupon_id ][ $index ] = $timestamp;
}
}
if ( ! empty( $gift_sending_timestamp ) ) {
$order->update_meta_data( 'gift_sending_timestamp', $gift_sending_timestamp );
}
}
if ( ! empty( $send_coupon_data['gift_receiver_message'] ) ) {
$gift_receiver_message = array();
if ( ! is_scalar( $send_coupon_data['gift_receiver_message'] ) ) {
foreach ( $send_coupon_data['gift_receiver_message'] as $key => $message ) {
list( $coupon_id, $index ) = explode( '_', $key );
$coupon_id = ( ! empty( $coupon_id ) ) ? intval( $coupon_id ) : 0;
$index = ( ! empty( $index ) ) ? intval( $index ) : 0;
if ( empty( $gift_receiver_message[ $coupon_id ] ) || ! is_array( $gift_receiver_message[ $coupon_id ] ) ) {
$gift_receiver_message[ $coupon_id ] = array();
}
$gift_receiver_message[ $coupon_id ][ $index ] = $message;
}
}
if ( ! empty( $gift_receiver_message ) ) {
$order->update_meta_data( 'gift_receiver_message', $gift_receiver_message );
}
}
$order->save();
},
10,
2
);
}
/**
* Registers the main JS file required to add filters and Slot/Fills.
*/
public function register_main_integration() {
$script_path = '/blocks/build/index.js';
$script_url = $this->get_plugin_directory_url( $script_path );
$script_asset_path = $this->get_plugin_directory( '/blocks/build/index.asset.php' );
$script_asset = file_exists( $script_asset_path )
? require $script_asset_path
: array(
'dependencies' => array( 'wp-i18n' ),
'version' => $this->get_file_version( $script_path ),
);
wp_register_script(
'woocommerce-smart-coupons-blocks-integration',
$script_url,
$script_asset['dependencies'],
$script_asset['version'],
true
);
wp_set_script_translations(
'woocommerce-smart-coupons-blocks-integration',
'woocommerce-smart-coupons',
$this->get_plugin_directory( '/languages' )
);
}
/**
* Returns an array of script handles to enqueue in the frontend context.
*
* @return string[]
*/
public function get_script_handles() {
return array( 'woocommerce-smart-coupons-blocks-integration', 'woocommerce-smart-coupons-available-coupons-block-frontend', 'woocommerce-smart-coupons-send-coupon-form-block-frontend' );
}
/**
* Returns an array of script handles to enqueue in the editor context.
*
* @return string[]
*/
public function get_editor_script_handles() {
return array( 'woocommerce-smart-coupons-blocks-integration', 'woocommerce-smart-coupons-available-coupons-block-editor', 'woocommerce-smart-coupons-send-coupon-form-block-editor' );
}
/**
* An array of key, value pairs of data made available to the block on the client side.
*
* @return array
*/
public function get_script_data() {
$data = array(
'woocommerce-smart-coupons-blocks-active' => true,
);
return $data;
}
/**
* Load script data for blocks
*/
public function load_script_data_for_blocks() {
$this->load_available_coupons_data();
$this->load_send_coupon_form_data();
}
/**
* Load data for available coupons block
*/
public function load_available_coupons_data() {
$smart_coupon_cart_page_text = get_option( 'smart_coupon_cart_page_text' );
$smart_coupon_cart_page_text = ( ! empty( $smart_coupon_cart_page_text ) ) ? $smart_coupon_cart_page_text : _x( 'Available Coupons (click on a coupon to use it)', 'Block editor & frontend', 'woocommerce-smart-coupons' );
$available_coupons_html = '';
$sample_coupon_html = '';
$auto_applied_coupons = array();
if ( ! class_exists( 'WC_SC_Coupon_Message' ) ) {
if ( file_exists( trailingslashit( WP_PLUGIN_DIR . '/' . WC_SC_PLUGIN_DIRNAME ) . 'includes/class-wc-sc-coupon-message.php' ) ) {
include_once trailingslashit( WP_PLUGIN_DIR . '/' . WC_SC_PLUGIN_DIRNAME ) . 'includes/class-wc-sc-coupon-message.php';
}
}
if ( ! class_exists( 'WC_SC_Display_Coupons' ) ) {
if ( file_exists( trailingslashit( WP_PLUGIN_DIR . '/' . WC_SC_PLUGIN_DIRNAME ) . 'includes/class-wc-sc-display-coupons.php' ) ) {
include_once trailingslashit( WP_PLUGIN_DIR . '/' . WC_SC_PLUGIN_DIRNAME ) . 'includes/class-wc-sc-display-coupons.php';
}
}
if ( ! class_exists( 'WC_SC_Auto_Apply_Coupon' ) ) {
if ( file_exists( trailingslashit( WP_PLUGIN_DIR . '/' . WC_SC_PLUGIN_DIRNAME ) . 'includes/class-wc-sc-auto-apply-coupon.php' ) ) {
include_once trailingslashit( WP_PLUGIN_DIR . '/' . WC_SC_PLUGIN_DIRNAME ) . 'includes/class-wc-sc-auto-apply-coupon.php';
}
}
if ( ! class_exists( 'WC_SC_Settings' ) ) {
if ( file_exists( trailingslashit( WP_PLUGIN_DIR . '/' . WC_SC_PLUGIN_DIRNAME ) . 'includes/class-wc-sc-settings.php' ) ) {
include_once trailingslashit( WP_PLUGIN_DIR . '/' . WC_SC_PLUGIN_DIRNAME ) . 'includes/class-wc-sc-settings.php';
}
}
if ( ! is_admin() && ! wp_doing_ajax() && ! WC()->is_rest_api_request() ) {
if ( class_exists( 'WC_SC_Coupon_Message' ) ) {
$wc_sc_coupon_message = WC_SC_Coupon_Message::get_instance();
ob_start();
$wc_sc_coupon_message->wc_coupon_message_display();
$available_coupons_html .= ob_get_clean();
}
if ( class_exists( 'WC_SC_Display_Coupons' ) ) {
$wc_sc_display_coupons = WC_SC_Display_Coupons::get_instance();
ob_start();
$wc_sc_display_coupons->show_available_coupons( $smart_coupon_cart_page_text );
$available_coupons_html .= ob_get_clean();
}
if ( class_exists( 'WC_SC_Auto_Apply_Coupon' ) ) {
$wc_sc_auto_apply_coupon = WC_SC_Auto_Apply_Coupon::get_instance();
$auto_applied_coupons = $wc_sc_auto_apply_coupon->get_auto_applied_coupons();
if ( ! empty( $auto_applied_coupons ) ) {
foreach ( $auto_applied_coupons as $index => $coupon_code ) {
if ( 'no' !== $wc_sc_auto_apply_coupon->is_auto_apply_coupon_removable( $coupon_code ) ) {
unset( $auto_applied_coupons[ $index ] );
}
}
}
$auto_applied_coupons = array_values( $auto_applied_coupons );
}
$design = get_option( 'wc_sc_setting_coupon_design', 'basic' );
if ( class_exists( 'WC_SC_Settings' ) ) {
$wc_sc_settings = WC_SC_Settings::get_instance();
ob_start();
for ( $i = 0; $i < 2; $i++ ) {
$wc_sc_settings->coupon_design_html( $design );
}
$sample_coupon_html = ob_get_clean();
}
}
$script_data = array(
'html' => $available_coupons_html,
'background_color' => get_option( 'wc_sc_setting_coupon_background_color', '#39cccc' ),
'foreground_color' => get_option( 'wc_sc_setting_coupon_foreground_color', '#30050b' ),
'third_color' => get_option( 'wc_sc_setting_coupon_third_color', '#39cccc' ),
'coupon_section_title' => $smart_coupon_cart_page_text,
'sample_html' => $sample_coupon_html,
'forced_auto_applied_coupons' => $auto_applied_coupons,
);
wp_localize_script( 'woocommerce-smart-coupons-available-coupons-block-frontend', 'wc_sc_available_coupons_block_editor', $script_data );
wp_localize_script( 'woocommerce-smart-coupons-available-coupons-block-editor', 'wc_sc_available_coupons_block_editor', $script_data );
wp_localize_script( 'woocommerce-smart-coupons-blocks-integration', 'wc_sc_available_coupons_block_editor', $script_data );
}
/**
* Load send coupon form data
*
* @return void
*/
public function load_send_coupon_form_data() {
$form_title = $this->sc_get_option( 'smart_coupon_gift_certificate_form_page_text', _x( 'Send Coupons to...', 'Block editor & frontend', 'woocommerce-smart-coupons' ) );
$form_title = ( ! empty( $form_title ) ) ? $form_title : _x( 'Send Coupons to...', 'Block editor & frontend', 'woocommerce-smart-coupons' );
$all_discount_types = wc_get_coupon_types();
$coupon_details_to_be_sent = array();
$cart_contents = ( ! empty( WC()->cart->cart_contents ) ) ? WC()->cart->cart_contents : array();
$coupon_ids_to_be_generated = array();
if ( ! empty( $cart_contents ) ) {
$sell_sc_at_less_price = get_option( 'smart_coupons_sell_store_credit_at_less_price', 'no' );
foreach ( $cart_contents as $product ) {
if ( ! empty( $product['variation_id'] ) ) {
$_product = wc_get_product( $product['variation_id'] );
} elseif ( ! empty( $product['product_id'] ) ) {
$_product = wc_get_product( $product['product_id'] );
} else {
continue;
}
$coupon_titles = $this->get_coupon_titles( array( 'product_object' => $_product ) );
$price = $_product->get_price();
if ( $coupon_titles ) {
foreach ( $coupon_titles as $coupon_title ) {
$coupon = new WC_Coupon( $coupon_title );
if ( ! is_object( $coupon ) || ! is_callable( array( $coupon, 'get_id' ) ) ) {
continue;
}
$coupon_id = $coupon->get_id();
if ( empty( $coupon_id ) ) {
continue;
}
$discount_type = $coupon->get_discount_type();
$coupon_amount = $this->get_amount( $coupon, true );
$pick_price_of_prod = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'is_pick_price_of_product' ) : get_post_meta( $coupon_id, 'is_pick_price_of_product', true );
if ( array_key_exists( $discount_type, $all_discount_types ) || ( 'yes' === $pick_price_of_prod && '' === $price ) || ( 'yes' === $pick_price_of_prod && '' !== $price && $coupon_amount > 0 ) ) {
$coupon_data = $this->get_coupon_meta_data( $coupon );
$coupon_id = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : '';
$coupon_code = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
$product_price = ( is_object( $product['data'] ) && is_callable( array( $product['data'], 'get_price' ) ) ) ? $product['data']->get_price() : 0;
$is_free_shipping = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_free_shipping' ) ) ) ? ( ( $coupon->get_free_shipping() ) ? 'yes' : 'no' ) : '';
$discount_type = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
$coupon_amount = $this->get_amount( $coupon, true );
for ( $i = 0; $i < $product['quantity']; $i++ ) {
if ( $this->is_coupon_amount_pick_from_product_price( array( $coupon_code ) ) ) {
if ( 'yes' === $sell_sc_at_less_price ) {
$_coupon_amount = ( is_object( $product['data'] ) && is_callable( array( $product['data'], 'get_regular_price' ) ) ) ? $product['data']->get_regular_price() : 0;
if ( empty( $_coupon_amount ) && ! empty( $product_price ) ) {
$_coupon_amount = $product_price;
}
} else {
$_coupon_amount = $product_price;
}
if ( empty( $_coupon_amount ) && ! empty( $product['credit_amount'] ) ) {
$_coupon_amount = (float) $product['credit_amount'];
$_coupon_amount = $this->read_price( $_coupon_amount, true );
}
} else {
$_coupon_amount = $coupon_amount;
}
if ( '' !== $_coupon_amount || $_coupon_amount > 0 || $coupon_amount > 0 || 'yes' === $is_free_shipping ) {
$formatted_coupon_text = '';
$formatted_coupon_amount = 0;
if ( ! empty( $_coupon_amount ) || ! empty( $coupon_amount ) ) {
$formatted_coupon_amount = ( $coupon_amount <= 0 ) ? wc_price( $_coupon_amount ) : $coupon_data['coupon_amount'];
$formatted_coupon_text .= $coupon_data['coupon_type'];
if ( 'yes' === $is_free_shipping ) {
$formatted_coupon_text .= ' &amp; ';
}
}
if ( 'yes' === $is_free_shipping ) {
$formatted_coupon_text .= _x( 'Free Shipping coupon', 'Block editor & frontend', 'woocommerce-smart-coupons' );
}
if ( 'smart_coupon' !== $discount_type && strpos( $formatted_coupon_text, 'coupon' ) === false ) {
$formatted_coupon_text .= ' ' . _x( 'coupon', 'Block editor & frontend', 'woocommerce-smart-coupons' );
}
$count_coupon_ids = array_count_values( $coupon_ids_to_be_generated );
$coupon_details_to_be_sent[] = (object) array(
'title' => _x( 'Send', 'Block editor & frontend', 'woocommerce-smart-coupons' ) . ' ' . $formatted_coupon_text . ' ' . _x( 'of', 'Block editor & frontend', 'woocommerce-smart-coupons' ) . ' ' . wp_strip_all_tags( $formatted_coupon_amount ),
'coupon_id' => $coupon_id,
'index' => ( ! empty( $count_coupon_ids ) && array_key_exists( $coupon_id, $count_coupon_ids ) ) ? $count_coupon_ids[ $coupon_id ] : 0,
);
$coupon_ids_to_be_generated[] = $coupon_id;
}
}
}
}
}
}
}
$script_data = array(
'is_display' => $this->sc_get_option( 'smart_coupons_display_coupon_receiver_details_form', 'yes' ),
'title' => $form_title,
'custom_text' => $this->sc_get_option( 'smart_coupon_gift_certificate_form_details_text', '' ),
'description' => _x( 'Your order contains coupons. What would you like to do?', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'is_schedule' => $this->sc_get_option( 'smart_coupons_schedule_store_credit', 'no' ),
'is_gift' => array(
(object) array(
'label' => _x( 'Send to me', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'value' => 'no',
),
(object) array(
'label' => _x( 'Gift to someone else', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'value' => 'yes',
),
),
'sc_send_to' => array(
(object) array(
'label' => _x( 'Send to one person', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'value' => 'one',
),
(object) array(
'label' => _x( 'Send to different people', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'value' => 'many',
),
),
'wc_sc_schedule_gift_sending' => array(
(object) array(
'label' => _x( 'now', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'value' => 'now',
),
(object) array(
'label' => _x( 'later', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'value' => 'later',
),
),
'deliver_coupon_label' => _x( 'Deliver coupon', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'gift_receiver_email_placeholder' => _x( 'Enter recipient e-mail address', 'Block editor & frontend', 'woocommerce-smart-coupons' ),
'coupon_details_to_be_sent' => $coupon_details_to_be_sent,
);
wp_localize_script( 'woocommerce-smart-coupons-send-coupon-form-block-frontend', 'wc_sc_send_coupon_form_block_frontend', $script_data );
wp_localize_script( 'woocommerce-smart-coupons-send-coupon-form-block-editor', 'wc_sc_send_coupon_form_block_editor', $script_data );
}
/**
* Get the file modified time as a cache buster if we're in dev mode.
*
* @param string $file Local path to the file.
* @return string The cache buster value to use for the given file.
*/
protected function get_file_version( $file ) {
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG && file_exists( $file ) ) {
return filemtime( $file );
}
return $this->get_version();
}
}

View File

@@ -0,0 +1,168 @@
<?php
/**
* Smart Coupons Block extend store endpoints
*
* @author StoreApps
* @since 8.7.0
* @version 1.0.0
*
* @package woocommerce-smart-coupons/blocks/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* WooCommerce Smart Coupons Extend Store API.
*
* A class to extend the store public API with Smart Coupons related data
*
* @package WooCommerce Smart Coupons
*/
use Automattic\WooCommerce\StoreApi\StoreApi;
use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema;
use Automattic\WooCommerce\StoreApi\Schemas\V1\CheckoutSchema;
if ( ! class_exists( 'WC_SC_Extend_Store_Endpoint' ) ) {
/**
* Extend store endpoint
*/
class WC_SC_Extend_Store_Endpoint {
/**
* Stores Rest Extending instance.
*
* @var ExtendSchema
*/
private static $extend;
/**
* Plugin Identifier, unique to each plugin.
*
* @var string
*/
const IDENTIFIER = 'woocommerce-smart-coupons';
/**
* Bootstraps the class and hooks required data.
*/
public static function init() {
self::$extend = Automattic\WooCommerce\StoreApi\StoreApi::container()->get( Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema::class );
self::extend_store();
}
/**
* Registers the actual data into each endpoint.
*/
public static function extend_store() {
if ( is_callable( array( self::$extend, 'register_endpoint_data' ) ) ) {
self::$extend->register_endpoint_data(
array(
'endpoint' => CheckoutSchema::IDENTIFIER,
'namespace' => self::IDENTIFIER,
'schema_callback' => array( 'WC_SC_Extend_Store_Endpoint', 'extend_checkout_schema' ),
'schema_type' => ARRAY_A,
)
);
}
}
/**
* Register subscription product schema into cart/items endpoint.
*
* @return array Registered schema.
*/
public static function extend_checkout_schema() {
return array(
'is_gift' => array(
'description' => _x( 'Whether to send coupons to someone else.', 'REST API', 'woocommerce-smart-coupons' ),
'type' => array( 'string', 'null' ),
'context' => array( 'view', 'edit' ),
'readonly' => true,
'optional' => true,
'arg_options' => array(
'validate_callback' => function( $value ) {
return is_string( $value );
},
'sanitize_callback' => 'sanitize_text_field',
),
),
'send_to' => array(
'description' => _x( 'Whether to send coupons to only one person or multiple people.', 'REST API', 'woocommerce-smart-coupons' ),
'type' => array( 'string', 'null' ),
'context' => array( 'view', 'edit' ),
'readonly' => true,
'arg_options' => array(
'validate_callback' => function( $value ) {
return is_string( $value );
},
'sanitize_callback' => 'sanitize_text_field',
),
),
'wc_sc_schedule_gift_sending' => array(
'description' => _x( 'Whether to send coupons now or schedule for later.', 'REST API', 'woocommerce-smart-coupons' ),
'type' => array( 'string', 'null' ),
'context' => array( 'view', 'edit' ),
'readonly' => true,
'arg_options' => array(
'validate_callback' => function( $value ) {
return is_string( $value );
},
'sanitize_callback' => 'sanitize_text_field',
),
),
'gift_receiver_email' => array(
'description' => _x( 'Email address of recipients', 'REST API', 'woocommerce-smart-coupons' ),
'type' => array( 'object', 'null' ),
'context' => array( 'view', 'edit' ),
'readonly' => true,
'arg_options' => array(
'validate_callback' => function( $value ) {
return is_array( $value );
},
'sanitize_callback' => 'wc_clean',
),
'items' => array(
'type' => 'string',
),
),
'gift_sending_timestamp' => array(
'description' => _x( 'Coupons scheduled date & time', 'REST API', 'woocommerce-smart-coupons' ),
'type' => array( 'object', 'null' ),
'context' => array( 'view', 'edit' ),
'readonly' => true,
'arg_options' => array(
'validate_callback' => function( $value ) {
return is_array( $value );
},
'sanitize_callback' => 'wc_clean',
),
'items' => array(
'type' => 'string',
),
),
'gift_receiver_message' => array(
'description' => _x( 'Message for coupon recipient', 'REST API', 'woocommerce-smart-coupons' ),
'type' => array( 'object', 'null' ),
'context' => array( 'view', 'edit' ),
'readonly' => true,
'arg_options' => array(
'validate_callback' => function( $value ) {
return is_array( $value );
},
'sanitize_callback' => 'wc_clean',
),
'items' => array(
'type' => 'string',
),
),
);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
<?php
/**
* Functions to register client-side assets (scripts and stylesheets) for the
* Gutenberg block.
*
* @author StoreApps
* @since 4.0.0
* @version 1.0
*
* @package woocommerce-smart-coupons/includes/blocks
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WC_SC_Gutenberg_Coupon_Block' ) ) {
/**
* Class for handling Smart Coupons Shortcode
*/
class WC_SC_Gutenberg_Coupon_Block {
/**
* Variable to hold instance of WC_SC_Gutenberg_Coupon_Block
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
global $wp_version;
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( is_plugin_active( 'gutenberg/gutenberg.php' ) || version_compare( $wp_version, '5.0', '>=' ) ) {
add_action( 'init', array( $this, 'gutenberg_coupon_block_init' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'gutenberg_coupon_add_inline_css' ) );
}
}
/**
* Get single instance of WC_SC_Gutenberg_Coupon_Block
*
* @return WC_SC_Gutenberg_Coupon_Block Singleton object of WC_SC_Gutenberg_Coupon_Block
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Registers all block assets so that they can be enqueued through Gutenberg in
* the corresponding context.
*
* @see https://wordpress.org/gutenberg/handbook/blocks/writing-your-first-block-type/#enqueuing-block-scripts
*/
public function gutenberg_coupon_block_init() {
// Skip block registration if Gutenberg is not enabled/merged.
if ( ! function_exists( 'register_block_type' ) ) {
return;
}
$dir = dirname( __FILE__ );
$index_js = 'sc-gutenberg-block.js';
wp_register_script(
'coupon-block-editor-js',
plugins_url( $index_js, __FILE__ ),
array(
'wp-blocks',
'wp-i18n',
'wp-element',
'wp-components',
),
filemtime( "$dir/$index_js" ),
true
);
if ( shortcode_exists( 'smart_coupons' ) ) {
register_block_type(
'woocommerce-smart-coupons/coupon',
array(
'editor_script' => 'coupon-block-editor-js',
'attributes' => array(
'coupon_code' => array( 'type' => 'string' ),
),
'render_callback' => array( WC_SC_Shortcode::get_instance(), 'execute_smart_coupons_shortcode' ),
)
);
}
}
/**
* Our componenet is referring to smart-coupon.css as main css file.
* We cannot add register/enqueue a new CSS file to render coupon design in Gutenberg.
* And hence we are adding necessary files via wp_add_inline_style.
*/
public function gutenberg_coupon_add_inline_css() {
if ( ! wp_style_is( 'smart-coupon' ) ) {
wp_enqueue_style( 'smart-coupon' );
}
$coupon_style_attributes = WC_Smart_Coupons::get_instance()->get_coupon_style_attributes();
$gutenberg_active_coupon_style = '
.gb-active-coupon {
' . $coupon_style_attributes . '
}
';
// Add the above custom CSS via wp_add_inline_style.
wp_add_inline_style( 'smart-coupon', $gutenberg_active_coupon_style );
}
}
}
WC_SC_Gutenberg_Coupon_Block::get_instance();

View File

@@ -0,0 +1,120 @@
/**
* WooCommerce Smart Coupons Gutenberg
*
* @author StoreApps
* @since 4.0.0
* @version 1.0
*
* @package woocommerce-smart-coupons/includes/blocks
*/
( function( wp ) {
/**
* Registers a new block provided a unique name and an object defining its behavior.
*
* @see https://github.com/WordPress/gutenberg/tree/master/blocks#api
*/
const {registerBlockType} = wp.blocks;
/**
* Returns a new element of given type. Element is an abstraction layer atop React.
*
* @see https://github.com/WordPress/gutenberg/tree/master/element#element
*/
const createElement = wp.element.createElement;
/**
* Retrieves the translation of text.
*
* @see https://github.com/WordPress/gutenberg/tree/master/i18n#api
*/
const {__} = wp.i18n;
/**
* Every block starts by registering a new block type definition.
*
* @see https://wordpress.org/gutenberg/handbook/block-api/
*/
registerBlockType(
'woocommerce-smart-coupons/coupon',
{
/**
* This is the display title for our block, which can be translated with `i18n` functions.
* The block inserter will show this name.
*/
title: __( 'Smart Coupons', 'woocommerce-smart-coupons' ),
/**
* This is the block description for our block, which can be translated with `il8n` functions.
*/
description: __( 'Show any WooCommerce coupon with Smart Coupons.' ),
/**
* Blocks are grouped into categories to help users browse and discover them.
* The categories provided by core are `common`, `embed`, `formatting`, `layout` and `widgets`.
*/
category: 'embed',
/**
* Define block icon for our block.
*/
icon: 'heart',
/**
* This are the block keywords using which our block can be searched.
*/
keywords: [
__( 'Smart' ),
__( 'Coupons' ),
__( 'Store Credit' ),
],
/**
* Optional block extended support features.
*/
supports: {
// Removes support for an HTML mode.
html: false,
// align: [ 'wide', 'full' ],.
},
attributes: {
coupon_code: {
type: 'string',
},
},
/**
* The edit function describes the structure of your block in the context of the editor.
* This represents what the editor will render when the block is used.
*
* @see https://wordpress.org/gutenberg/handbook/block-edit-save/#edit
*
* @param {Object} [props] Properties passed from the editor.
* @return {Element} Element to render.
*/
edit: function( props ){
return createElement(
wp.editor.RichText,
{
className: 'coupon-container gb-active-coupon',
value: props.attributes.coupon_code,
onChange: function( coupon_code ) {
props.setAttributes( { coupon_code: coupon_code } );
}
}
);
},
/**
* The save function defines the way in which the different attributes should be combined
* into the final markup, which is then serialized by Gutenberg into `post_content`.
*
* @see https://wordpress.org/gutenberg/handbook/block-edit-save/#save
*
* @return {Element} Element to render.
*/
save:function( props ){
return null;
}
}
);
} )( window.wp );

View File

@@ -0,0 +1,273 @@
<?php
/**
* Smart Coupons Initialize
*
* @author StoreApps
* @since 3.3.0
* @version 1.4.0
* @package WooCommerce Smart Coupons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Act_Deact' ) ) {
/**
* Class for handling actions to be performed during initialization
*/
class WC_SC_Act_Deact {
/**
* Database changes required for Smart Coupons
*
* Add option 'smart_coupon_email_subject' if not exists
* Enable 'Auto Generation' for Store Credit (discount_type: 'smart_coupon') not having any customer_email
* Disable 'apply_before_tax' for all Store Credit (discount_type: 'smart_coupon')
*/
public static function smart_coupon_activate() {
set_transient( '_smart_coupons_process_activation', 1, 30 );
if ( ! is_network_admin() && ! isset( $_GET['activate-multi'] ) ) { // phpcs:ignore
set_transient( '_smart_coupons_activation_redirect', 1, 30 );
}
}
/**
* Process activation
*/
public static function process_activation() {
global $wpdb, $blog_id, $woocommerce_smart_coupon;
$is_migrate_site_options = get_site_option( 'wc_sc_migrate_site_options', 'yes' );
if ( 'yes' === $is_migrate_site_options ) {
// phpcs:disable
$default_options = array(
'all_tasks_count_woo_sc', // => '',.
'bulk_coupon_action_woo_sc', // => '',.
'current_time_woo_sc', // => '',.
'remaining_tasks_count_woo_sc', // => '',.
'smart_coupons_combine_emails', // => 'no',.
'smart_coupons_is_send_email', // => 'yes',.
'start_time_woo_sc', // => '',.
'wc_sc_auto_apply_coupon_ids', // => maybe_serialize( array() ),.
'wc_sc_is_show_terms_notice', // => 'yes',.
'wc_sc_terms_page_id', // => '',.
'woocommerce_wc_sc_combined_email_coupon_settings', // => maybe_serialize( array() ),.
'woocommerce_wc_sc_email_coupon_settings', // => maybe_serialize( array() ),.
'woo_sc_action_data', // => '',.
'woo_sc_generate_coupon_posted_data', // => '',.
);
// phpcs:enable
$existing_options = array();
foreach ( $default_options as $option_name ) {
$site_option = get_site_option( $option_name );
if ( ! empty( $site_option ) ) {
$existing_options[ $option_name ] = $site_option;
}
}
}
if ( is_multisite() ) {
$blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}", 0 ); // WPCS: cache ok, db call ok.
} else {
$blog_ids = array( $blog_id );
}
if ( ! get_option( 'smart_coupon_email_subject' ) ) {
add_option( 'smart_coupon_email_subject' );
}
if ( ! is_object( $woocommerce_smart_coupon ) || ! is_a( $woocommerce_smart_coupon, 'WC_Smart_Coupons' ) || ! is_callable( array( $woocommerce_smart_coupon, 'update_post_meta' ) ) ) {
if ( ! class_exists( 'WC_Smart_Coupons' ) ) {
if ( file_exists( WP_PLUGIN_DIR . '/woocommerce-smart-coupons/includes/class-wc-smart-coupons.php' ) ) {
include_once WP_PLUGIN_DIR . '/woocommerce-smart-coupons/includes/class-wc-smart-coupons.php';
}
if ( class_exists( 'WC_Smart_Coupons' ) && is_callable( array( 'WC_Smart_Coupons', 'get_instance' ) ) ) {
$woocommerce_smart_coupon = WC_Smart_Coupons::get_instance();
}
}
}
if ( is_multisite() ) {
require_once ABSPATH . WPINC . '/ms-blogs.php';
}
foreach ( $blog_ids as $blogid ) {
if ( ( file_exists( WP_PLUGIN_DIR . '/woocommerce/woocommerce.php' ) ) && ( is_plugin_active( 'woocommerce/woocommerce.php' ) ) ) {
if ( is_multisite() ) {
switch_to_blog( $blogid );
}
$results = $wpdb->get_col(
$wpdb->prepare(
"SELECT postmeta.post_id FROM {$wpdb->prefix}postmeta as postmeta WHERE postmeta.meta_key = %s AND postmeta.meta_value = %s AND postmeta.post_id IN
(SELECT p.post_id FROM {$wpdb->prefix}postmeta AS p WHERE p.meta_key = %s AND p.meta_value = %s) ",
'discount_type',
'smart_coupon',
'customer_email',
'a:0:{}'
)
); // WPCS: cache ok, db call ok.
foreach ( $results as $result ) {
if ( is_object( $woocommerce_smart_coupon ) && is_callable( array( $woocommerce_smart_coupon, 'update_post_meta' ) ) ) {
$woocommerce_smart_coupon->update_post_meta( $result, 'auto_generate_coupon', 'yes' );
} else {
update_post_meta( $result, 'auto_generate_coupon', 'yes' );
}
}
// To disable apply_before_tax option for Gift Certificates / Store Credit.
$tax_post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM {$wpdb->prefix}postmeta WHERE meta_key = %s AND meta_value = %s", 'discount_type', 'smart_coupon' ) ); // WPCS: cache ok, db call ok.
foreach ( $tax_post_ids as $tax_post_id ) {
if ( is_object( $woocommerce_smart_coupon ) && is_callable( array( $woocommerce_smart_coupon, 'update_post_meta' ) ) ) {
$woocommerce_smart_coupon->update_post_meta( $tax_post_id, 'apply_before_tax', 'no' );
} else {
update_post_meta( $tax_post_id, 'apply_before_tax', 'no' );
}
}
if ( 'yes' === $is_migrate_site_options ) {
$results = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
"SELECT option_id,
option_name,
option_value
FROM {$wpdb->prefix}options
WHERE option_name IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",
'smart_coupons_is_send_email',
'smart_coupons_combine_emails',
'woocommerce_wc_sc_combined_email_coupon_settings',
'woocommerce_wc_sc_email_coupon_settings',
'wc_sc_is_show_terms_notice',
'wc_sc_terms_page_id',
'woo_sc_generate_coupon_posted_data',
'start_time_woo_sc',
'current_time_woo_sc',
'all_tasks_count_woo_sc',
'remaining_tasks_count_woo_sc',
'bulk_coupon_action_woo_sc',
'woo_sc_action_data',
'wc_sc_auto_apply_coupon_ids'
),
ARRAY_A
);
if ( ! empty( $results ) ) {
foreach ( $results as $result ) {
$option_value = ( ! empty( $existing_options[ $result['option_name'] ] ) ) ? $existing_options[ $result['option_name'] ] : '';
if ( ! empty( $option_value ) ) {
if ( is_array( $option_value ) ) {
$option_value = maybe_serialize( $option_value );
}
$wpdb->query( // phpcs:ignore
$wpdb->prepare(
"INSERT INTO {$wpdb->prefix}options (option_id, option_name, option_value, autoload)
VALUES (%d,%s,%s,%s)
ON DUPLICATE KEY UPDATE option_value = %s",
$result['option_id'],
$result['option_name'],
$option_value,
'no',
$option_value
)
);
}
}
}
}
if ( is_multisite() ) {
restore_current_blog(); // phpcs:ignore
}
}
}
if ( 'yes' === $is_migrate_site_options ) {
update_site_option( 'wc_sc_migrate_site_options', 'no' );
}
$woocommerce_smart_coupon->maybe_sync_orders_prior_to_800();
}
/**
* Database changes required for Smart Coupons
*
* Delete option 'sc_display_global_coupons' if exists
*/
public static function smart_coupon_deactivate() {
global $woocommerce_smart_coupon;
if ( get_option( 'sc_display_global_coupons' ) !== false ) {
delete_option( 'sc_display_global_coupons' );
}
if ( false === ( get_option( 'sc_flushed_rules' ) ) || 'found' === ( get_option( 'sc_flushed_rules' ) ) ) {
delete_option( 'sc_flushed_rules' );
}
self::clear_cache();
if ( ! is_object( $woocommerce_smart_coupon ) || ! is_a( $woocommerce_smart_coupon, 'WC_Smart_Coupons' ) || ! is_callable( array( $woocommerce_smart_coupon, 'update_post_meta' ) ) ) {
if ( ! class_exists( 'WC_Smart_Coupons' ) ) {
if ( file_exists( WP_PLUGIN_DIR . '/woocommerce-smart-coupons/includes/class-wc-smart-coupons.php' ) ) {
include_once WP_PLUGIN_DIR . '/woocommerce-smart-coupons/includes/class-wc-smart-coupons.php';
}
if ( class_exists( 'WC_Smart_Coupons' ) && is_callable( array( 'WC_Smart_Coupons', 'get_instance' ) ) ) {
$woocommerce_smart_coupon = WC_Smart_Coupons::get_instance();
}
}
}
$woocommerce_smart_coupon->record_latest_800_order();
}
/**
* Clear cache
*
* @return string $message
*/
public static function clear_cache() {
$all_cache_key = get_option( 'wc_sc_all_cache_key' );
if ( ! empty( $all_cache_key ) ) {
$cleared_cache = array();
foreach ( $all_cache_key as $key ) {
$is_cleared = wp_cache_delete( $key );
if ( true === $is_cleared ) {
$cleared_cache[] = $key;
}
}
// phpcs:disable
// if ( count( $all_cache_key ) === count( $cleared_cache ) ) {
// update_option( 'wc_sc_all_cache_key', array(), 'no' );
// /* translators: Number of all cache key */
// $message = sprintf( __( 'Successfully cleared %d cache!', 'woocommerce-smart-coupons' ), count( $all_cache_key ) );
// } else {
// $remaining = array_diff( $all_cache_key, $cleared_cache );
// update_option( 'wc_sc_all_cache_key', $remaining, 'no' );
// /* translators: 1. Number of cache not deleted 2. Number of all cache key */
// $message = sprintf( __( 'Failed! Could not clear %1$d out of %2$d cache', 'woocommerce-smart-coupons' ), count( $remaining ), count( $all_cache_key ) );
// }
// phpcs:enable
// There's no method in WordPress to detect if the cache is added successfully.
// Therefore it's not possible to know whether it is deleted or not.
// Hence returning a success message always.
// Enable above block of code when we can detect saving & deleting of cache.
}
return __( 'Successfully cleared WooCommerce Smart Coupons cache!', 'woocommerce-smart-coupons' );
}
}
}

View File

@@ -0,0 +1,426 @@
<?php
/**
* Actions for coupons dashboard
*
* @author StoreApps
* @since 4.4.0
* @version 1.5.0
* @package WooCommerce Smart Coupons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Admin_Coupons_Dashboard_Actions' ) ) {
/**
* Class for actions on coupons dashboard
*/
class WC_SC_Admin_Coupons_Dashboard_Actions {
/**
* Variable to hold instance of WC_SC_Admin_Coupons_Dashboard_Actions
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_filter( 'post_row_actions', array( $this, 'woocommerce_sc_add_custom_actions' ), 1, 2 );
add_action( 'admin_action_duplicate_coupon', array( $this, 'woocommerce_duplicate_coupon_action' ) );
add_action( 'admin_footer', array( $this, 'add_post_row_script' ) );
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name Function to call.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return mixed Result of function call.
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Get single instance of WC_SC_Admin_Coupons_Dashboard_Actions
*
* @return WC_SC_Admin_Coupons_Dashboard_Actions Singleton object of WC_SC_Admin_Coupons_Dashboard_Actions
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Add Smart Coupons actions on WC Coupons dashboard
*
* @param array $actions Array of existing actions.
* @param WP_Post $post Post object.
* @return array $actions including duplicate action of coupons
*/
public function woocommerce_sc_add_custom_actions( $actions, $post ) {
if ( 'shop_coupon' !== $post->post_type ) {
return $actions;
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return $actions;
}
$coupon_code = ( ! empty( $post->post_title ) ) ? $post->post_title : '';
$coupon_id = ( ! empty( $post->ID ) ) ? $post->ID : 0;
$shop_page_id = get_option( 'woocommerce_shop_page_id', 0 );
if ( ! empty( $shop_page_id ) ) {
$shop_page_id = 'shop';
} else {
$home_url = home_url();
$shop_page_id = ( function_exists( 'wpcom_vip_url_to_postid' ) ) ? wpcom_vip_url_to_postid( $home_url ) : url_to_postid( $home_url ); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid
}
if ( empty( $shop_page_id ) ) {
$shop_page_id = 'cart';
}
$coupon_share_url = add_query_arg(
array(
'coupon-code' => $coupon_code,
'sc-page' => $shop_page_id,
),
home_url( '/' )
);
$actions['copy'] = '<a href="#" id="sc-click-to-copy-' . esc_attr( $coupon_id ) . '" onclick="sc_copy_to_clipboard(' . "'" . esc_js( $coupon_code ) . "'" . ')" data-clipboard-action="copy" data-clipboard-target=".row-title" title="' . __( 'Copy this coupon code', 'woocommerce-smart-coupons' ) . '" rel="permalink">' . __( 'Copy', 'woocommerce-smart-coupons' ) . '</a>';
$actions['share-link'] = '<a href="#" id="sc-click-to-share-' . esc_attr( $coupon_id ) . '" onclick="sc_copy_to_clipboard(' . "'" . esc_js( $coupon_share_url ) . "'" . ')" data-clipboard-action="copy" data-clipboard-target=".row-title" title="' . __( 'Copy coupon shareable link and apply via URL', 'woocommerce-smart-coupons' ) . '" rel="permalink">' . __( 'Get shareable link', 'woocommerce-smart-coupons' ) . '</a>';
if ( function_exists( 'duplicate_post_plugin_activation' ) ) {
return $actions;
} else {
$actions['duplicate'] = '<a href="' . esc_url( wp_nonce_url( admin_url( 'admin.php?action=duplicate_coupon&amp;post=' . $coupon_id ), 'woocommerce-duplicate-coupon_' . $coupon_id ) ) . '" title="' . __( 'Make a duplicate from this coupon', 'woocommerce-smart-coupons' ) . '" rel="permalink">' . __( 'Duplicate', 'woocommerce-smart-coupons' ) . '</a>';
}
return $actions;
}
/**
* Function to insert post meta values for duplicate coupon
*
* @param int $id ID of parent coupon.
* @param int $new_id ID of duplicated coupon.
*/
public function woocommerce_duplicate_coupon_post_meta( $id, $new_id ) {
global $wpdb;
$meta_keys = array( 'expiry_date', 'usage_count', '_used_by', 'date_expires' );
$how_many = count( $meta_keys );
$placeholders = array_fill( 0, $how_many, '%s' );
$post_meta_infos = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=%d AND meta_key NOT IN ( " . implode( ',', $placeholders ) . ' )', array_merge( array( $id ), $meta_keys ) ) ); // phpcs:ignore
if ( 0 !== count( $post_meta_infos ) ) {
$sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) ";
foreach ( $post_meta_infos as $meta_info ) {
$meta_key = $meta_info->meta_key;
$meta_value = $meta_info->meta_value;
$sql_query_sel[] = $wpdb->prepare( 'SELECT %d, %s, %s', $new_id, $meta_key, $meta_value );
}
$sql_query .= implode( ' UNION ALL ', $sql_query_sel );
$wpdb->query( $sql_query ); // phpcs:ignore
}
}
/**
* Function to duplicate post taxonomies for the duplicate coupon
*
* @param int $id ID of parent coupon.
* @param int $new_id ID of duplicated coupon.
* @param string $post_type Post type being duplicated.
*/
public function woocommerce_duplicate_coupon_post_taxonomies( $id, $new_id, $post_type ) {
$taxonomies = get_object_taxonomies( $post_type );
foreach ( $taxonomies as $taxonomy ) {
$post_terms = wp_get_object_terms( $id, $taxonomy );
$post_terms_count = count( $post_terms );
for ( $i = 0; $i < $post_terms_count; $i++ ) {
wp_set_object_terms( $new_id, $post_terms[ $i ]->slug, $taxonomy, true );
}
}
}
/**
* Function to create duplicate coupon and copy all properties of the coupon to duplicate coupon
*
* @param WP_Post $post Post object.
* @param int $parent Post parent ID.
* @param string $post_status Post status.
* @return int $new_post_id
*/
public function woocommerce_create_duplicate_from_coupon( $post, $parent = 0, $post_status = '' ) {
global $wpdb;
$new_post_author = wp_get_current_user();
$new_post_date = current_time( 'mysql' );
$new_post_date_gmt = get_gmt_from_date( $new_post_date );
if ( $parent > 0 ) {
$post_parent = $parent;
$post_status = $post_status ? $post_status : 'publish';
$suffix = '';
} else {
$post_parent = $post->post_parent;
$post_status = $post_status ? $post_status : 'draft';
$suffix = __( '(Copy)', 'woocommerce-smart-coupons' );
}
$new_post_type = $post->post_type;
$post_content = str_replace( "'", "''", $post->post_content );
$post_content_filtered = str_replace( "'", "''", $post->post_content_filtered );
$post_excerpt = str_replace( "'", "''", $post->post_excerpt );
$post_title = strtolower( str_replace( "'", "''", $post->post_title ) . $suffix );
$post_name = str_replace( "'", "''", $post->post_name );
$comment_status = str_replace( "'", "''", $post->comment_status );
$ping_status = str_replace( "'", "''", $post->ping_status );
$wpdb->insert(
$wpdb->posts,
array(
'post_author' => $new_post_author->ID,
'post_date' => $new_post_date,
'post_date_gmt' => $new_post_date_gmt,
'post_content' => $post_content,
'post_content_filtered' => $post_content_filtered,
'post_title' => $post_title,
'post_excerpt' => $post_excerpt,
'post_status' => $post_status,
'post_type' => $new_post_type,
'comment_status' => $comment_status,
'ping_status' => $ping_status,
'post_password' => $post->post_password,
'to_ping' => $post->to_ping,
'pinged' => $post->pinged,
'post_modified' => $new_post_date,
'post_modified_gmt' => $new_post_date_gmt,
'post_parent' => 0, // No need to link it with any other coupon.
'menu_order' => $post->menu_order,
'post_mime_type' => $post->post_mime_type,
)
); // WPCS: db call ok.
$new_post_id = $wpdb->insert_id;
$this->woocommerce_duplicate_coupon_post_taxonomies( $post->ID, $new_post_id, $post->post_type );
$this->woocommerce_duplicate_coupon_post_meta( $post->ID, $new_post_id );
return $new_post_id;
}
/**
* Function to return post id of the duplicate coupon to be created
*
* @param int $id ID of the coupon to duplicate.
* @return object $post Duplicated post object.
*/
public function woocommerce_get_coupon_to_duplicate( $id ) {
global $wpdb;
$post = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID=%d", $id ) ); // WPCS: cache ok, db call ok.
if ( isset( $post->post_type ) && 'revision' === $post->post_type ) {
$id = $post->post_parent;
$post = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID=%d", $id ) ); // WPCS: cache ok, db call ok.
}
return $post[0];
}
/**
* Function to validate condition and create duplicate coupon
*/
public function woocommerce_duplicate_coupon() {
if ( empty( $_REQUEST['post'] ) || ( isset( $_REQUEST['action'] ) && 'duplicate_post_save_as_new_page' === $_REQUEST['action'] ) ) { // phpcs:ignore
wp_die( esc_html__( 'No coupon to duplicate has been supplied!', 'woocommerce-smart-coupons' ) );
}
// Get the original page.
$id = absint( $_REQUEST['post'] ); // WPCS: input var ok.
check_admin_referer( 'woocommerce-duplicate-coupon_' . $id );
$post = $this->woocommerce_get_coupon_to_duplicate( $id );
if ( isset( $post ) && null !== $post ) {
$new_id = $this->woocommerce_create_duplicate_from_coupon( $post );
// If you have written a plugin which uses non-WP database tables to save
// information about a page you can hook this action to dupe that data.
do_action( 'woocommerce_duplicate_coupon', $new_id, $post );
// Redirect to the edit screen for the new draft page.
wp_safe_redirect( admin_url( 'post.php?action=edit&post=' . $new_id ) );
exit;
} else {
/* translators: %d: Post ID */
wp_die( sprintf( esc_html__( 'Coupon creation failed, could not find original coupon: %d', 'woocommerce-smart-coupons' ), esc_html( $id ) ) );
}
}
/**
* Function to call function to create duplicate coupon
*/
public function woocommerce_duplicate_coupon_action() {
$coupon_id = ( ! empty( $_REQUEST['post'] ) ) ? absint( $_REQUEST['post'] ) : 0;
check_admin_referer( 'woocommerce-duplicate-coupon_' . $coupon_id );
$action = ( ! empty( $_REQUEST['action'] ) ) ? wc_clean( wp_unslash( $_REQUEST['action'] ) ) : ''; // phpcs:ignore
if ( 'duplicate_coupon' !== $action ) {
return;
}
if ( $this->is_wc_gte_30() ) {
$coupon = new WC_Coupon( $coupon_id );
if ( false === $coupon ) {
/* translators: %s: coupon id */
wp_die( sprintf( esc_html__( 'Coupon creation failed, could not find original coupon: %s', 'woocommerce-smart-coupons' ), esc_html( $coupon_id ) ) );
}
$duplicate = $this->coupon_duplicate( $coupon );
// Hook rename to match other woocommerce_coupon_* hooks, and to move away from depending on a response from the wp_posts table.
do_action( 'wc_sc_duplicate_coupon', $duplicate, $coupon );
// Redirect to the edit screen for the new draft page.
wp_safe_redirect( admin_url( 'post.php?action=edit&post=' . $duplicate->get_id() ) );
exit;
} else {
$this->woocommerce_duplicate_coupon();
}
}
/**
* Duplicate coupon
*
* @param WC_Coupon $coupon The coupon object to duplicate.
* @return WC_Coupon $duplicate The duplicated coupon.
*/
public function coupon_duplicate( $coupon = null ) {
/**
* Filter to allow us to exclude meta keys from coupon duplication..
*
* @param array $exclude_meta The keys to exclude from the duplicate.
* @param array $existing_meta_keys The meta keys that the coupon already has.
* @since 7.2.0
*/
$meta_to_exclude = array_filter(
apply_filters(
'wc_sc_duplicate_coupon_exclude_meta',
array(),
array_map(
function ( $meta ) {
return $meta->key;
},
$coupon->get_meta_data()
)
)
);
$duplicate = clone $coupon;
$duplicate->set_id( 0 );
/* translators: %s contains the code of the original coupon. */
$duplicate->set_code( sprintf( '%s-copy', $duplicate->get_code() ) );
$duplicate->set_date_created( null );
$duplicate->set_usage_count( 0 );
$duplicate->set_used_by( array() );
$duplicate->set_date_expires( null );
if ( $this->is_wc_greater_than( '6.1.2' ) && $this->is_callable( $duplicate, 'set_status' ) ) {
$duplicate->set_status( 'draft' );
}
foreach ( $meta_to_exclude as $meta_key ) {
$duplicate->delete_meta_data( $meta_key );
}
/**
* This action can be used to modify the object further before it is created - it will be passed by reference.
*
* @since 3.0
*/
do_action( 'wc_sc_coupon_duplicate_before_save', $duplicate, $coupon );
// Save parent coupon.
$duplicate_id = $duplicate->save();
$duplicate = new WC_Coupon( $duplicate );
$this->woocommerce_duplicate_coupon_post_taxonomies( $coupon->get_id(), $duplicate_id, 'shop_coupon' );
if ( $this->is_wc_greater_than( '6.1.2' ) && $this->is_callable( $duplicate, 'get_status' ) ) {
$coupon_status = $duplicate->get_status();
} else {
$coupon_status = get_post_status( $duplicate_id );
}
if ( ! empty( $duplicate_id ) && 'draft' !== $coupon_status ) {
$args = array(
'ID' => $duplicate_id,
'post_status' => 'draft',
);
wp_update_post( $args ); // Because $coupon->set_status( 'draft' ) not working.
}
return new WC_Coupon( $duplicate_id );
}
/**
* Function to copy and share coupon via jQuery.
*/
public function add_post_row_script() {
$screen = get_current_screen();
if ( 'edit-shop_coupon' === $screen->id ) {
?>
<script type="text/javascript" class="sc-copy-share">
function sc_copy_to_clipboard(copyElement) {
var copyText = copyElement;
var temp = jQuery('<input>');
jQuery("body").append(temp);
temp.val(copyText).select();
document.execCommand("copy");
temp.remove();
}
</script>
<?php
}
}
}
}
WC_SC_Admin_Coupons_Dashboard_Actions::get_instance();

View File

@@ -0,0 +1,485 @@
<?php
/**
* Smart Coupons Admin Notifications
*
* @author StoreApps
* @since 4.0.0
* @version 1.6.0
*
* @package woocommerce-smart-coupons/includes/
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WC_SC_Admin_Notifications' ) ) {
/**
* Class for handling admin pages of Smart Coupons
*/
class WC_SC_Admin_Notifications {
/**
* Variable to hold instance of WC_SC_Admin_Notifications
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_filter( 'plugin_action_links_' . plugin_basename( WC_SC_PLUGIN_FILE ), array( $this, 'plugin_action_links' ) );
add_action( 'wp_ajax_wc_sc_review_notice_action', array( $this, 'wc_sc_review_notice_action' ) );
add_action( 'wp_ajax_wc_sc_40_notice_action', array( $this, 'wc_sc_40_notice_action' ) );
add_action( 'admin_notices', array( $this, 'show_plugin_notice' ) );
// To update footer text on SC screens.
add_filter( 'admin_footer_text', array( $this, 'wc_sc_footer_text' ) );
add_filter( 'update_footer', array( $this, 'wc_sc_update_footer_text' ), 99 );
// To show 'Connect your store' notice of WC Helper on SC pages.
add_filter( 'woocommerce_screen_ids', array( $this, 'add_wc_connect_store_notice_on_sc_pages' ) );
// Show Database update notices.
add_action( 'admin_notices', array( $this, 'admin_db_update_notices' ) );
}
/**
* Get single instance of WC_SC_Admin_Pages
*
* @return WC_SC_Admin_Pages Singleton object of WC_SC_Admin_Pages
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Function to add more action on plugins page
*
* @param array $links Existing links.
* @return array $links
*/
public function plugin_action_links( $links ) {
$action_links = array(
'settings' => '<a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=wc-smart-coupons' ) ) . '">' . esc_html__( 'Settings', 'woocommerce-smart-coupons' ) . '</a>',
'faqs' => '<a href="' . esc_url( admin_url( 'admin.php?page=sc-faqs' ) ) . '">' . esc_html__( 'FAQ\'s', 'woocommerce-smart-coupons' ) . '</a>',
'docs' => '<a target="_blank" href="' . esc_url( 'https://woocommerce.com/document/smart-coupons/' ) . '">' . __( 'Docs', 'woocommerce-smart-coupons' ) . '</a>',
'support' => '<a target="_blank" href="' . esc_url( 'https://woocommerce.com/my-account/create-a-ticket/' ) . '">' . __( 'Support', 'woocommerce-smart-coupons' ) . '</a>',
'review' => '<a target="_blank" href="' . esc_url( 'https://woocommerce.com/products/smart-coupons/?review' ) . '">' . __( 'Review', 'woocommerce-smart-coupons' ) . '</a>',
);
return array_merge( $action_links, $links );
}
/**
* Handle Smart Coupons review notice action
*/
public function wc_sc_review_notice_action() {
check_ajax_referer( 'wc-sc-review-notice-action', 'security' );
$post_do = ( ! empty( $_POST['do'] ) ) ? wc_clean( wp_unslash( $_POST['do'] ) ) : ''; // phpcs:ignore
$option = strtotime( '+1 month' );
if ( 'remove' === $post_do ) {
$option = 'no';
}
update_option( 'wc_sc_is_show_review_notice', $option, 'no' );
wp_send_json( array( 'success' => 'yes' ) );
}
/**
* Handle Smart Coupons version 4.0.0 notice action
*/
public function wc_sc_40_notice_action() {
check_ajax_referer( 'wc-sc-40-notice-action', 'security' );
update_option( 'wc_sc_is_show_40_notice', 'no', 'no' );
wp_send_json( array( 'success' => 'yes' ) );
}
/**
* Show plugin review notice
*/
public function show_plugin_notice() {
global $pagenow, $post;
$valid_post_types = array( 'shop_coupon', 'shop_order', 'product' );
$valid_pagenow = array( 'edit.php', 'post.php', 'plugins.php' );
$is_show_review_notice = get_option( 'wc_sc_is_show_review_notice' );
$is_coupon_enabled = get_option( 'woocommerce_enable_coupons' );
$get_post_type = ( ! empty( $post->ID ) ) ? $this->get_post_type( $post->ID ) : '';
$get_page = ( ! empty( $_GET['page'] ) ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
$get_tab = ( ! empty( $_GET['tab'] ) ) ? wc_clean( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore
$design = get_option( 'wc_sc_setting_coupon_design', 'basic' );
$is_page = ( in_array( $pagenow, $valid_pagenow, true ) || in_array( $get_post_type, $valid_post_types, true ) || ( 'admin.php' === $pagenow && ( 'wc-smart-coupons' === $get_page || 'wc-smart-coupons' === $get_tab ) ) );
if ( $is_page && 'yes' !== $is_coupon_enabled ) {
?>
<div id="wc_sc_coupon_disabled" class="updated fade error">
<p>
<?php
echo '<strong>' . esc_html__( 'Important', 'woocommerce-smart-coupons' ) . ':</strong> ' . esc_html__( 'Setting "Enable the use of coupon codes" is disabled.', 'woocommerce-smart-coupons' ) . ' ' . sprintf(
'<a href="%s">%s</a>',
esc_url(
add_query_arg(
array(
'page' => 'wc-settings',
'tab' => 'general',
),
admin_url( 'admin.php' )
)
),
esc_html__( 'Enable', 'woocommerce-smart-coupons' )
) . ' ' . esc_html__( 'it to use', 'woocommerce-smart-coupons' ) . ' <strong>' . esc_html__( 'WooCommerce Smart Coupons', 'woocommerce-smart-coupons' ) . '</strong> ' . esc_html__( 'features.', 'woocommerce-smart-coupons' );
?>
</p>
</div>
<?php
}
// Review Notice.
if ( $is_page && ! empty( $is_show_review_notice ) && 'no' !== $is_show_review_notice && time() >= absint( $is_show_review_notice ) ) {
if ( ! wp_script_is( 'jquery' ) ) {
wp_enqueue_script( 'jquery' );
}
?>
<style type="text/css" media="screen">
#wc_sc_review_notice .wc_sc_review_notice_action {
float: right;
padding: 0.5em 0;
text-align: right;
}
</style>
<script type="text/javascript">
jQuery(function(){
jQuery('body').on('click', '#wc_sc_review_notice .wc_sc_review_notice_action a.wc_sc_review_notice_remind', function( e ){
jQuery.ajax({
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
type: 'post',
dataType: 'json',
data: {
action: 'wc_sc_review_notice_action',
security: '<?php echo esc_html( wp_create_nonce( 'wc-sc-review-notice-action' ) ); ?>',
do: 'remind'
},
success: function( response ){
if ( response.success != undefined && response.success != '' && response.success == 'yes' ) {
jQuery('#wc_sc_review_notice').fadeOut(500, function(){ jQuery('#wc_sc_review_notice').remove(); });
}
}
});
return false;
});
jQuery('body').on('click', '#wc_sc_review_notice .wc_sc_review_notice_action a.wc_sc_review_notice_remove', function(){
jQuery.ajax({
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
type: 'post',
dataType: 'json',
data: {
action: 'wc_sc_review_notice_action',
security: '<?php echo esc_html( wp_create_nonce( 'wc-sc-review-notice-action' ) ); ?>',
do: 'remove'
},
success: function( response ){
if ( response.success != undefined && response.success != '' && response.success == 'yes' ) {
jQuery('#wc_sc_review_notice').fadeOut(500, function(){ jQuery('#wc_sc_review_notice').remove(); });
}
}
});
return false;
});
});
</script>
<div id="wc_sc_review_notice" class="updated fade">
<div class="wc_sc_review_notice_action">
<a href="javascript:void(0)" class="wc_sc_review_notice_remind"><?php echo esc_html__( 'Remind me after a month', 'woocommerce-smart-coupons' ); ?></a><br>
<a href="javascript:void(0)" class="wc_sc_review_notice_remove"><?php echo esc_html__( 'Never show again', 'woocommerce-smart-coupons' ); ?></a>
</div>
<p>
<?php echo esc_html__( 'Awesome, you successfully auto-generated a coupon! Are you having a great experience with', 'woocommerce-smart-coupons' ) . ' <strong>' . esc_html__( 'WooCommerce Smart Coupons', 'woocommerce-smart-coupons' ) . '</strong> ' . esc_html__( 'so far?', 'woocommerce-smart-coupons' ) . '<br>' . esc_html__( 'Please consider', 'woocommerce-smart-coupons' ) . ' <a href="' . esc_url( 'https://woocommerce.com/products/smart-coupons/#reviews' ) . '">' . esc_html__( 'leaving a review', 'woocommerce-smart-coupons' ) . '</a> ' . esc_html__( '! If things aren\'t going quite as expected, we\'re happy to help -- please reach out to', 'woocommerce-smart-coupons' ) . ' <a href="' . esc_url( 'https://woocommerce.com/my-account/create-a-ticket/' ) . '">' . esc_html__( 'our support team', 'woocommerce-smart-coupons' ) . '</a>.'; ?>
</p>
</div>
<?php
}
if ( $is_page && 'custom-design' === $design ) {
?>
<div class="updated fade error" style="background-color: #f0fff0;">
<p>
<?php
echo sprintf(
/* translators: 1: WooCommerce Smart Coupons 2: Link for the Smart Coupons settings */
esc_html__( '%1$s: You are using a custom coupon style which is planned to be removed from the plugin in upcoming versions. New, improved styles & colors are added in the version 4.9.0. We would request you to choose a color scheme & a style for coupon from the newly added colors & styles. You can do this from %2$s.', 'woocommerce-smart-coupons' ),
'<strong>' . esc_html__( 'WooCommerce Smart Coupons', 'woocommerce-smart-coupons' ) . '</strong>',
'<a href="' . esc_url(
add_query_arg(
array(
'page' => 'wc-settings',
'tab' => 'wc-smart-coupons',
),
admin_url( 'admin.php' )
)
) . '" target="_blank">' . esc_html__(
'Smart Coupons settings',
'woocommerce-smart-coupons'
) . '</a>'
);
?>
</p>
</div>
<?php
}
}
/**
* Function to 'Connect your store' notice on Smart Coupons pages in admin
*
* @param string $sc_rating_text Text in footer (left).
* @return string $sc_rating_text
*/
public function wc_sc_footer_text( $sc_rating_text ) {
global $post, $pagenow;
if ( ! empty( $pagenow ) ) {
$get_post_type = ( ! empty( $post->ID ) ) ? $this->get_post_type( $post->ID ) : '';
$get_page = ( ! empty( $_GET['page'] ) ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
$get_tab = ( ! empty( $_GET['tab'] ) ) ? wc_clean( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore
$sc_pages = array( 'wc-smart-coupons', 'sc-about', 'sc-faqs' );
if ( in_array( $get_page, $sc_pages, true ) || 'shop_coupon' === $get_post_type || 'wc-smart-coupons' === $get_tab ) {
?>
<style type="text/css">
#wpfooter {
display: block !important;
}
</style>
<?php
/* translators: %s: link to review WooCommerce Smart Coupons */
$sc_rating_text = wp_kses_post( sprintf( __( 'Liked WooCommerce Smart Coupons? Leave us a %s. A huge thank you from WooCommerce & StoreApps in advance!', 'woocommerce-smart-coupons' ), '<a target="_blank" href="' . esc_url( 'https://woocommerce.com/products/smart-coupons/?review' ) . '" style="color: #5850EC;">5-star rating here</a>' ) );
}
}
return $sc_rating_text;
}
/**
* Function to 'Connect your store' notice on Smart Coupons pages in admin
*
* @param string $sc_text Text in footer (right).
* @return string $sc_text
*/
public function wc_sc_update_footer_text( $sc_text ) {
global $post, $pagenow;
if ( ! empty( $pagenow ) ) {
$get_post_type = ( ! empty( $post->ID ) ) ? $this->get_post_type( $post->ID ) : '';
$get_page = ( ! empty( $_GET['page'] ) ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
$get_tab = ( ! empty( $_GET['tab'] ) ) ? wc_clean( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore
$sc_pages = array( 'wc-smart-coupons', 'sc-about', 'sc-faqs' );
if ( in_array( $get_page, $sc_pages, true ) || 'shop_coupon' === $get_post_type || 'wc-smart-coupons' === $get_tab ) {
/* translators: %s: link to submit idea for Smart Coupons on WooCommerce idea board */
$sc_text = sprintf( __( 'Have a feature request? Submit it %s.', 'woocommerce-smart-coupons' ), '<a href="' . esc_url( 'https://woocommerce.com/feature-requests/smart-coupons/' ) . '" target="_blank" style="color: #5850EC;">' . __( 'here', 'woocommerce-smart-coupons' ) . '</a>' );
}
}
return $sc_text;
}
/**
* Function to 'Connect your store' notice on Smart Coupons pages in admin
*
* @param array $screen_ids List of existing screen ids.
* @return array $screen_ids
*/
public function add_wc_connect_store_notice_on_sc_pages( $screen_ids ) {
array_push( $screen_ids, 'woocommerce_page_wc-smart-coupons' );
return $screen_ids;
}
/**
* Function to render admin notice
*
* @param string $type Notice type.
* @param string $title Notice title.
* @param string $message Notice message.
* @param string $action Notice actions.
* @param bool $dismissible Notice dismissible.
* @return void.
*/
public function show_notice( $type = 'info', $title = '', $message = '', $action = '', $dismissible = false ) {
$css_classes = array(
'notice',
'notice-' . $type,
);
if ( true === $dismissible ) {
$css_classes[] = 'is-dismissible';
}
?>
<div class="<?php echo esc_attr( implode( ' ', $css_classes ) ); ?>">
<?php
if ( ! empty( $title ) ) {
printf( '<p><strong>%s</strong></p>', esc_html( $title ) );
}
if ( ! empty( $message ) ) {
printf( '<p>%s</p>', esc_html( $message ) );
}
if ( ! empty( $action ) ) {
printf( '<p class="submit">%s</p>', wp_kses_post( $action ) );
}
?>
</div>
<?php
}
/**
* Function to show database update notice
*/
public function admin_db_update_notices() {
if ( ! class_exists( 'WC_SC_Background_Upgrade' ) ) {
include_once 'class-wc-sc-background-upgrade.php';
}
$wcsc_db = WC_SC_Background_Upgrade::get_instance();
$update_status = $wcsc_db->get_status( '4.28.0' );
if ( 'pending' === $update_status ) {
// Notice for pending update.
$this->db_update_pending_notice();
} elseif ( 'processing' === $update_status ) {
// Notice for processing update.
$this->db_update_processing_notice();
} elseif ( 'completed' === $update_status ) {
// Notice for completed update.
$this->db_update_completed_notice();
$wcsc_db->set_status( '4.28.0', 'done' );
}
}
/**
* Function to show pending database update notice
*/
public function db_update_pending_notice() {
global $woocommerce_smart_coupon;
$plugin_version = $woocommerce_smart_coupon->get_smart_coupons_version();
/* translators: %s: Plugin name */
$title = sprintf( __( '%s database update required', 'woocommerce-smart-coupons' ), 'WooCommerce Smart Coupons' );
$message = __( 'The database update process runs in the background and may take a little while, so please be patient.', 'woocommerce-smart-coupons' );
$update_url = wp_nonce_url(
add_query_arg(
array(
'page' => 'wc-settings',
'tab' => 'wc-smart-coupons',
'wc_sc_update' => '4.28.0',
),
admin_url( 'admin.php' )
),
'wc_sc_db_process',
'wc_sc_db_update_nonce'
);
$action_button = sprintf( '<a href="%1$s" class="button button-primary">%2$s</a>', esc_url( $update_url ), __( 'Update database', 'woocommerce-smart-coupons' ) );
$this->show_notice( 'warning', $title, $message, $action_button );
}
/**
* Function to show database update processing notice.
*/
public function db_update_processing_notice() {
if ( 'woocommerce_page_wc-status' === $this->get_current_screen_id() && isset( $_GET['tab'] ) && 'action-scheduler' === wc_clean( wp_unslash( $_GET['tab'] ) ) ) { // phpcs:ignore
return;
}
$actions_url = add_query_arg(
array(
'page' => 'wc-status',
'tab' => 'action-scheduler',
's' => 'move_applied_coupon_options_to_transient',
'status' => 'pending',
),
admin_url( 'admin.php' )
);
$cron_disabled = defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON;
/* translators: %s: Plugin name */
$message = sprintf( __( '%s is updating the database in the background. The database update process may take a little while, so please be patient.', 'woocommerce-smart-coupons' ), 'WooCommerce Smart Coupons' );
if ( true === $cron_disabled ) {
$message .= '<br>' . __( 'Note: WP CRON has been disabled on your install which may prevent this update from completing.', 'woocommerce-smart-coupons' );
}
$action_button = sprintf( '<a href="%1$s" class="button button-secondary">%2$s</a>', esc_url( $actions_url ), __( 'View status', 'woocommerce-smart-coupons' ) );
$this->show_notice( 'info', '', $message, $action_button );
}
/**
* Function to show database update completed notice.
*/
public function db_update_completed_notice() {
/* translators: %s: Plugin name */
$message = sprintf( __( '%s database update completed. Thank you for updating to the latest version!', 'woocommerce-smart-coupons' ), 'WooCommerce Smart Coupons' );
$this->show_notice( 'success', '', $message, '', true );
}
/**
* Function to get current screen id.
*
* @return string.
*/
public function get_current_screen_id() {
$screen = get_current_screen();
return $screen ? $screen->id : '';
}
}
}
WC_SC_Admin_Notifications::get_instance();

View File

@@ -0,0 +1,504 @@
<?php
/**
* A Welcome page for store admin
*
* @author StoreApps
* @since 3.3.0
* @version 1.4.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Admin_Welcome' ) ) {
/**
* WC_SC_Admin_Welcome class
*/
class WC_SC_Admin_Welcome {
/**
* Variable to hold instance of WC_SC_Admin_Welcome
*
* @var $instance
*/
private static $instance = null;
/**
* Hook in tabs.
*/
private function __construct() {
add_action( 'admin_menu', array( $this, 'admin_menus' ) );
add_action( 'admin_head', array( $this, 'admin_head' ) );
add_action( 'admin_init', array( $this, 'sc_welcome' ) );
}
/**
* Get single instance of WC_SC_Admin_Welcome
*
* @return WC_SC_Admin_Welcome Singleton object of WC_SC_Admin_Welcome
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Add admin menus/screens.
*/
public function admin_menus() {
$get_page = ( ! empty( $_GET['page'] ) ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
if ( empty( $get_page ) ) {
return;
}
$welcome_page_name = __( 'About Smart Coupons', 'woocommerce-smart-coupons' );
$welcome_page_title = __( 'Welcome to Smart Coupons', 'woocommerce-smart-coupons' );
$parent_slug = ( $this->is_wc_gte_44() ) ? 'woocommerce-marketing' : 'woocommerce';
switch ( $get_page ) {
case 'sc-about':
add_submenu_page( $parent_slug, $welcome_page_title, $welcome_page_name, 'manage_options', 'sc-about', array( $this, 'about_screen' ) );
break;
case 'sc-faqs':
add_submenu_page( $parent_slug, $welcome_page_title, $welcome_page_name, 'manage_options', 'sc-faqs', array( $this, 'faqs_screen' ) );
break;
}
}
/**
* Add styles just for this page, and remove dashboard page links.
*/
public function admin_head() {
$parent_slug = ( $this->is_wc_gte_44() ) ? 'woocommerce-marketing' : 'woocommerce';
remove_submenu_page( $parent_slug, 'sc-about' );
remove_submenu_page( $parent_slug, 'sc-faqs' );
$get_page = ( ! empty( $_GET['page'] ) ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
if ( ! empty( $get_page ) && ( 'sc-faqs' === $get_page || 'sc-about' === $get_page ) ) {
?>
<style type="text/css">
/*<![CDATA[*/
.about-wrap h3 {
margin-top: 1em;
margin-right: 0em;
margin-bottom: 0.1em;
}
.about-wrap .button-primary {
margin-top: 18px;
}
.about-wrap .button-hero {
color: #FFF!important;
border-color: #03a025!important;
background: #03a025 !important;
box-shadow: 0 1px 0 #03a025;
font-size: 1em;
font-weight: bold;
}
.about-wrap .button-hero:hover {
color: #FFF!important;
background: #0AAB2E!important;
border-color: #0AAB2E!important;
}
.about-wrap p {
margin-top: 0.6em;
margin-bottom: 0.8em;
}
.about-wrap .feature-section {
padding-bottom: 5px;
}
.about-wrap .aligncenter {
text-align: center;
}
.about-wrap,
.about-wrap .has-2-columns,
.about-wrap .has-3-columns {
max-width: unset !important;
}
ul.sc-top-features {
list-style-type: disc !important;
padding-left: 1.5em !important;
}
/*]]>*/
</style>
<?php
}
}
/**
* Intro text/links shown on all about pages.
*/
private function intro() {
if ( is_callable( 'WC_Smart_Coupons::get_smart_coupons_plugin_data' ) ) {
$plugin_data = WC_Smart_Coupons::get_smart_coupons_plugin_data();
$version = $plugin_data['Version'];
} else {
$version = '';
}
?>
<h1><?php echo esc_html__( 'Thank you for installing WooCommerce Smart Coupons', 'woocommerce-smart-coupons' ) . ' ' . esc_html( $version ) . '!'; ?></h1>
<p class="about-text"><?php echo esc_html__( 'Glad to have you onboard. We hope WooCommerce Smart Coupons adds to your desired success 🏆', 'woocommerce-smart-coupons' ); ?></p>
<div class="has-2-columns feature-section col two-col" style="margin-bottom: 30px !important;">
<div class="is-vertically-aligned-center column col">
<a href="<?php echo esc_url( admin_url( 'edit.php?post_type=shop_coupon' ) ); ?>" class="button button-hero"><?php echo esc_html__( 'Go To Coupons', 'woocommerce-smart-coupons' ); ?></a>
</div>
<div class="is-vertically-aligned-center column col last-feature">
<p class="alignright">
<?php
$settings_tab_url = add_query_arg(
array(
'page' => 'wc-settings',
'tab' => 'wc-smart-coupons',
),
admin_url( 'admin.php' )
);
?>
<a href="<?php echo esc_url( $settings_tab_url ); ?>" class="button button-primary" target="_blank"><?php echo esc_html__( 'Settings', 'woocommerce-smart-coupons' ); ?></a>
<a href="<?php echo esc_url( apply_filters( 'smart_coupons_docs_url', 'https://woocommerce.com/document/smart-coupons/', 'woocommerce-smart-coupons' ) ); ?>" class="docs button button-primary" target="_blank"><?php echo esc_html__( 'Docs', 'woocommerce-smart-coupons' ); ?></a>
</p>
</div>
</div>
<h2 class="nav-tab-wrapper">
<a class="nav-tab
<?php
$get_page = ( ! empty( $_GET['page'] ) ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
if ( 'sc-about' === $get_page ) {
echo 'nav-tab-active';
}
?>
" href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'sc-about' ), 'admin.php' ) ) ); ?>">
<?php echo esc_html__( 'Know Smart Coupons', 'woocommerce-smart-coupons' ); ?>
</a>
<a class="nav-tab
<?php
if ( 'sc-faqs' === $get_page ) {
echo 'nav-tab-active';
}
?>
" href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'sc-faqs' ), 'admin.php' ) ) ); ?>">
<?php echo esc_html__( "FAQ's", 'woocommerce-smart-coupons' ); ?>
</a>
</h2>
<?php
}
/**
* Output the about screen.
*/
public function about_screen() {
if ( ! wp_script_is( 'jquery' ) ) {
wp_enqueue_script( 'jquery' );
}
?>
<script type="text/javascript">
jQuery(function(){
jQuery('#toplevel_page_woocommerce').find('a[href$=shop_coupon]').addClass('current');
jQuery('#toplevel_page_woocommerce').find('a[href$=shop_coupon]').parent().addClass('current');
});
</script>
<div class="wrap about-wrap">
<?php $this->intro(); ?>
<div>
<div class="has-3-columns feature-section col three-col">
<div class="column col">
<h4><?php echo esc_html__( 'What is Smart Coupons?', 'woocommerce-smart-coupons' ); ?></h4>
<p>
<?php echo esc_html__( 'Smart Coupons is a powerful extension, built on top of WooCommerce coupons. It adds a new discount type - Store Credit - and advanced functionality to the default coupons.', 'woocommerce-smart-coupons' ); ?>
<?php echo esc_html__( 'Smart Coupons enable coupons to become an automatic/interactive system.', 'woocommerce-smart-coupons' ); ?>
</p>
</div>
<div class="column col">
<h4><?php echo esc_html__( 'Top Smart Coupons features', 'woocommerce-smart-coupons' ); ?></h4>
<ul class="sc-top-features">
<li><?php echo esc_html__( 'Create and gift Store Credit / Gift Cards', 'woocommerce-smart-coupons' ); ?></li>
<li><?php echo esc_html__( 'Bulk generate coupons', 'woocommerce-smart-coupons' ); ?></li>
<li><?php echo esc_html__( 'Apply multiple coupons via URL', 'woocommerce-smart-coupons' ); ?></li>
<li><?php echo esc_html__( 'Advanced restrictions - payment, shipping, location, user roles, product attributes', 'woocommerce-smart-coupons' ); ?></li>
</ul>
<p>
<?php echo esc_html__( 'and a lot more…', 'woocommerce-smart-coupons' ); ?>
</p>
</div>
<div class="column col last-feature">
<h4><?php echo esc_html__( 'Automatic payment for subscription renewals', 'woocommerce-smart-coupons' ); ?></h4>
<p>
<?php
/* translators: WooCommerce Subscriptions product link */
echo sprintf( esc_html__( 'If your store is using %s and your customer has purchased a subscription using a Store Credit. If that store credit has balance left in it, store will automatically use it for renewing that subscription.', 'woocommerce-smart-coupons' ), '<a href="https://woocommerce.com/products/woocommerce-subscriptions/?aff=5475">' . esc_html__( 'WooCommerce Subscriptions', 'woocommerce-smart-coupons' ) . '</a>' );
?>
</p>
</div>
</div>
<center><h3><?php echo esc_html__( 'How to use Smart Coupons the best way', 'woocommerce-smart-coupons' ); ?></h3></center>
<div class="has-3-columns feature-section col three-col">
<div class="column col">
<h4><?php echo esc_html__( 'Sell or issue store credit / gift cards', 'woocommerce-smart-coupons' ); ?></h4>
<p>
<?php
/* translators: 1: Affiliate For WooCommerce 2: Smart Manager 3: Smart Offers */
echo sprintf( esc_html__( 'Let customers purchase gift cards from you or you issue store credit that your users can redeem on the current or next purchase. See how: %1$s or %2$s', 'woocommerce-smart-coupons' ), ' <a href="https://woocommerce.com/document/smart-coupons/how-to-sell-gift-card-of-any-amount/" target="_blank">' . esc_html__( 'any amount', 'woocommerce-smart-coupons' ) . '</a>', '<a href="https://woocommerce.com/document/smart-coupons/how-to-sell-gift-card-of-variable-but-a-fixed-amount/" target="_blank">' . esc_html__( 'variable but fixed amount', 'woocommerce-smart-coupons' ) . '</a>.' );
?>
</p>
</div>
<div class="column col">
<h4><?php echo esc_html__( 'Bulk create unique coupons & email them', 'woocommerce-smart-coupons' ); ?></h4>
<p>
<?php echo esc_html__( 'Import and export unique coupons in bulk via CSV. Share coupon codes to deal sites or email them to your customers.', 'woocommerce-smart-coupons' ) . ' <a href="https://woocommerce.com/document/smart-coupons/how-to-bulk-generate-coupons/" target="_blank">' . esc_html__( 'See how', 'woocommerce-smart-coupons' ) . '</a>.'; ?>
</p>
</div>
<div class="column col last-feature">
<h4><?php echo esc_html__( 'Gift a product via coupon', 'woocommerce-smart-coupons' ); ?></h4>
<p>
<?php echo esc_html__( 'Attach a gift of any value (free or paid product) to a particular coupon. Here, instead of a discount, a product is redeemed for the coupon code.', 'woocommerce-smart-coupons' ) . ' <a href="https://woocommerce.com/document/smart-coupons/how-to-gift-a-product-via-coupon/" target="_blank">' . esc_html__( 'See how', 'woocommerce-smart-coupons' ) . '</a>.'; ?>
</p>
</div>
</div>
<div class="has-3-columns feature-section col three-col">
<div class="column col">
<h4><?php echo esc_html__( 'Give discounts to customers for next purchase', 'woocommerce-smart-coupons' ); ?></h4>
<p>
<?php echo esc_html__( 'You can give a coupon to your customer after every purchase, which can encourage them to purchase again from you.', 'woocommerce-smart-coupons' ) . ' <a href="https://woocommerce.com/document/smart-coupons/how-to-give-coupons-with-products-for-next-order/" target="_blank">' . esc_html__( 'See how', 'woocommerce-smart-coupons' ) . '</a>.'; ?>
</p>
</div>
<div class="column col">
<h4><?php echo esc_html__( 'Set a maximum discount limit', 'woocommerce-smart-coupons' ); ?></h4>
<p>
<?php echo esc_html__( 'Give bigger discounts without hurting your profits. Offer a percentage off coupon upto a particular value. Example - Flat 50% off upto $100.', 'woocommerce-smart-coupons' ); ?>
</p>
</div>
<div class="column col last-feature">
<h4><?php echo esc_html__( 'Make customer\'s coupon usage, easy & simple', 'woocommerce-smart-coupons' ); ?></h4>
<p>
<?php echo esc_html__( 'Show only valid coupons to your customer (if logged in) on cart, checkout & My Account page. Coupons can be applied with single click. So, no need to remember the coupon code or copy-pasting.', 'woocommerce-smart-coupons' ); ?>
</p>
</div>
</div>
</div>
</div>
<?php
}
/**
* Output the FAQ's screen.
*/
public function faqs_screen() {
if ( ! wp_script_is( 'jquery' ) ) {
wp_enqueue_script( 'jquery' );
}
?>
<script type="text/javascript">
jQuery(function(){
jQuery('#toplevel_page_woocommerce').find('a[href$=shop_coupon]').addClass('current');
jQuery('#toplevel_page_woocommerce').find('a[href$=shop_coupon]').parent().addClass('current');
});
</script>
<div class="wrap about-wrap">
<?php $this->intro(); ?>
<h3 class="aligncenter"><?php echo esc_html__( 'FAQ / Common Problems', 'woocommerce-smart-coupons' ); ?></h3>
<?php
$faqs = array(
array(
'que' => esc_html__( 'When trying to add coupon/Smart Coupon, I get "Invalid post type" message.', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Make sure use of coupon is enabled in your store. You can find this setting', 'woocommerce-smart-coupons' ) . ' <a href="' . add_query_arg(
array(
'page' => 'wc-settings',
'tab' => 'general',
),
admin_url( 'admin.php' )
) . '" target="_blank">' . __( 'here', 'woocommerce-smart-coupons' ) . '</a>.',
),
array(
'que' => esc_html__( 'Smart Coupon\'s fields are broken?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Make sure you are using the ', 'woocommerce-smart-coupons' ) . '<a target="_blank" href="http://dzv365zjfbd8v.cloudfront.net/changelogs/woocommerce-smart-coupons/changelog.txt">' . __( 'latest version of Smart Coupons', 'woocommerce-smart-coupons' ) . '</a>' . esc_html__( '. If still the issue persist, temporarily de-activate all plugins except WooCommerce & Smart Coupons. Re-check the issue, if the issue still persists, contact us (from the link at the end of this page). If the issue goes away, re-activate other plugins one-by-one & re-checking the fields, to find out which plugin is conflicting.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'How to translate texts from Smart Coupons?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Simplest method is by installing', 'woocommerce-smart-coupons' ) . ' <a href="https://wordpress.org/plugins/loco-translate/" target="_blank">' . esc_html__( 'Loco Translate', 'woocommerce-smart-coupons' ) . '</a> ' . esc_html__( 'plugin and then following steps listed ', 'woocommerce-smart-coupons' ) . ' <a href="https://woocommerce.com/document/smart-coupons/how-to-translate-smart-coupons/" target="_blank">' . __( 'here', 'woocommerce-smart-coupons' ) . '</a>.',
),
array(
'que' => esc_html__( 'How to change texts of the emails sent from Smart Coupons?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'You can do this by overriding the email template.', 'woocommerce-smart-coupons' ) . ' <a href="https://woocommerce.com/document/smart-coupons/how-to-change-replace-and-override-email-template/" target="_blank">' . esc_html__( 'How to override email template', 'woocommerce-smart-coupons' ) . '</a>.',
),
array(
'que' => esc_html__( 'Can coupon code have any spaces in the name? / My Store Credit/Gift Certificate is not working (not generating new coupon code).', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'No. Coupon code should not have any spaces in the name, Eg, Coupon code should be “gift-certificate” & not “gift certificate”.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'What\'s the URL to a coupon, so it\'s automatically inserted when visiting?', 'woocommerce-smart-coupons' ),
/* translators: Documentation link for 'How to Apply Single or Multiple Coupons on Click of a Link' */
'ans' => esc_html__( 'URL of coupon should be like this:', 'woocommerce-smart-coupons' ) . ' <code>https://www.mysite.com/?coupon-code=discount5&sc-page=shop</code> ' . esc_html__( '. Replace www.mysite.com with your own site URL and replace discount5 with the your coupon code.', 'woocommerce-smart-coupons' ) . ' ' . sprintf( esc_html__( 'For more details you can refer to this article: %s', 'woocommerce-smart-coupons' ), '<a href="https://woocommerce.com/document/smart-coupons/how-to-apply-single-or-multiple-coupons-on-click-of-a-link/" target="_blank">' . esc_html__( 'How to Apply Single or Multiple Coupons on Click of a Link', 'woocommerce-smart-coupons' ) . '</a>' ),
),
array(
'que' => esc_html__( 'Do not want to tie store credit to be used by only one customer? / Can a customer send a gift certificate to themselves to pass on to someone else?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Edit the main coupon which is entered in "Coupons" field of the product edit page, then go to "Usage Restrictions" > "Disable Email Restriction" and disable this setting and save the coupon.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'Getting \'Page Not Found Error\' when accessing Coupons tab from My Account Page?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Go to WordPress -> Settings -> Permalinks and click on Save Settings once.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'Is there any reference file for creating an import file for coupons?', 'woocommerce-smart-coupons' ),
/* translators: 1. File name 2. File download link */
'ans' => sprintf( esc_html__( 'There is one file which is located inside the plugin. You can download the %1$s file from %2$s.', 'woocommerce-smart-coupons' ), '<code>sample.csv</code>', '<a href="' . esc_url( plugins_url( dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/sample.csv' ) ) . '">' . esc_html__( 'here', 'woocommerce-smart-coupons' ) . '</a>' ) . ' ' . esc_html__( 'If you want to import coupon through file, the file should be like', 'woocommerce-smart-coupons' ) . ' <code>sample.csv</code>',
),
array(
'que' => esc_html__( 'Available coupons are not visible on Cart, Checkout & My Account page?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Smart Coupons uses hooks of Cart, Checkout & My Account page to display available coupons. If your theme is not using those hooks in cart, checkout & my-account template, coupons will not be displayed.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'How can I resend gift card coupon bought by customers?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'You can resend them from order admin edit page.', 'woocommerce-smart-coupons' ) . ' <a href="https://woocommerce.com/document/smart-coupons/how-to-resend-coupons-generated-from-an-order-to-the-buyer/" target="_blank">' . __( 'See how', 'woocommerce-smart-coupons' ) . '</a>.',
),
array(
'que' => esc_html__( 'Uncheck "Auto-generate" option in Store Credit is not saving? Is it always checked?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Store Credit\'s default behavior is auto-generate because, when using a store credit, it\'s balance keeps reducing. Therefore it should be uniquely created for every user automatically.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'Smart Coupons is not sending emails.', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Smart Coupons sends email only after order completion. So make sure that order complete email is enabled and sending. If enabled, then make sure all settings of coupons, products are in place. Also check by switching your theme.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( '"Store Credit Receiver detail" form not appearing on checkout page?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'This form is displayed using a hook which is available in My Account template. Make sure your theme\'s my-account template contains all hooks required for that template. Update your theme if it is not updated.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'Does Smart Coupons allow printing of coupon as Gift Card?', 'woocommerce-smart-coupons' ),
/* translators: Documentation link for 'How to Print Coupons' */
'ans' => sprintf( esc_html__( 'Yes, Smart Coupons does provide a feature for printing coupons. For more details, check this article: %s', 'woocommerce-smart-coupons' ), '<a href="https://woocommerce.com/document/smart-coupons/how-to-print-coupons/" target="_blank">' . esc_html__( 'How to Print Coupons', 'woocommerce-smart-coupons' ) . '</a>' ),
),
array(
'que' => esc_html__( 'Is it possible to have a coupon for each variation of the variable product?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'From version 4.11.0, you can add/link coupons to product variations as well. This feature is not available in a version lower than 4.11.0.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'Is Smart Coupons compatible with WooCommerce Subscriptions?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Yes, Smart Coupons does work with WooCommerce Subscriptions.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'Which features of Smart Coupons work with Subscriptions?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Give away a discount or credit on signing up a subscription, give away recurring discount or credits, apply credit during sign up, automatic payment for renewals from credit (Note: When using PayPal Standard Gateway, store credit can be applied only during sign up. Automatic payment for renewals by credit will not work for PayPal Standard Gateway).', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'How does automatic payment by store credit work with Subscriptions?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Customers can apply store credit on a subscription during purchase of subscription. If the same store credit has sufficient balance, it\'ll keep applying it to renewals till the remainder in store credit is higher than renewal price. Customers will be able to apply store credit only during signup. They will not get an option to apply store credit in renewals. But if the store credit will not have sufficient balance to pay for the renewals, then the order will go into pending mode. Now when the customer will go to pay for this renewal order, they\'ll get an option to apply store credit again. To activate the subscription again, the customer will have to pay for the renewals. When the customer is paying for the renewals from their account, then in that process they can use the same store credit which didn\'t have the sufficient balance, again & pay for the remaining amount.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'Is it possible to partially pay for a subscription with store credit and the remainder by another method?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'No, this is possible only in those cases where subscription amount is more than store credit\'s balance. If store credit\'s balance is more than subscription\'s total then your bank account or credit card will not be charged.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'Is Smart Coupons WPML compatible?', 'woocommerce-smart-coupons' ),
'ans' => esc_html__( 'Not yet, but this is being worked on. You will find this in later versions.', 'woocommerce-smart-coupons' ),
),
array(
'que' => esc_html__( 'I\'m using WPML & WPML provides support for multi-currency, but Smart Coupons only changes currency symbol & the price value remains same. Can Smart Coupons change the currency symbol and the price value associated with it?', 'woocommerce-smart-coupons' ),
/* translators: Link for the plugin 'Aelia Currency Switcher for WooCommerce' */
'ans' => sprintf( esc_html__( 'Currently, Smart Coupons is compatible with %s. But it is not compatible with any other multi-currency plugin or with WPML.', 'woocommerce-smart-coupons' ), '<a href="https://aelia.co/shop/currency-switcher-woocommerce/" target="_blank">' . esc_html__( 'Aelia Currency Switcher for WooCommerce', 'woocommerce-smart-coupons' ) . '</a>' ),
),
);
$faqs = array_chunk( $faqs, 2 );
$right_faq_numbering = 1;
$left_faq_numbering = 0;
echo '<div>';
foreach ( $faqs as $fqs ) {
echo '<div class="has-2-columns two-col">';
foreach ( $fqs as $index => $faq ) {
echo '<div' . ( ( 1 === absint( $index ) ) ? ' class="column col last-feature"' : ' class="column col"' ) . '>';
echo '<h4>' . ( ( 1 === absint( $index ) ) ? $right_faq_numbering : ( $left_faq_numbering + 1 ) ) . '. ' . $faq['que'] . '</h4>'; // phpcs:ignore
echo '<p>' . $faq['ans'] . '</p>'; // phpcs:ignore
echo '</div>';
$right_faq_numbering++;
$left_faq_numbering++;
}
echo '</div>';
}
echo '</div>';
?>
<div class="aligncenter">
<h3>
<?php
/* translators: WooCommerce My Account support link */
echo sprintf( __( 'If you are facing any issues, please %s from your WooCommerce account.', 'woocommerce-smart-coupons' ), '<a target="_blank" href="https://woocommerce.com/my-account/create-a-ticket/">' . esc_html__( 'submit a ticket', 'woocommerce-smart-coupons' ) . '</a>' ); // phpcs:ignore
?>
</h3>
</div>
</div>
<?php
}
/**
* Sends user to the welcome page on first activation.
*/
public function sc_welcome() {
if ( ! get_transient( '_smart_coupons_activation_redirect' ) ) {
return;
}
// Delete the redirect transient.
delete_transient( '_smart_coupons_activation_redirect' );
wp_safe_redirect( admin_url( 'admin.php?page=sc-about' ) );
exit;
}
}
}
WC_SC_Admin_Welcome::get_instance();

View File

@@ -0,0 +1,402 @@
<?php
/**
* Smart Coupons Ajax Actions
*
* @author StoreApps
* @since 3.3.0
* @version 1.7.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Ajax' ) ) {
/**
* Class for handling ajax actions for Smart Coupons
*/
class WC_SC_Ajax {
/**
* Variable to hold instance of WC_SC_Ajax
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'wp_ajax_sc_json_search_coupons', array( $this, 'sc_json_search_coupons' ) );
add_action( 'wp_ajax_sc_json_search_storewide_coupons', array( $this, 'sc_json_search_storewide_coupons' ) );
add_action( 'wp_ajax_smart_coupons_json_search', array( $this, 'smart_coupons_json_search' ) );
add_action( 'wp_ajax_hide_notice_delete_after_usage', array( $this, 'hide_notice_delete_after_usage' ) );
}
/**
* Get single instance of WC_SC_Ajax
*
* @return WC_SC_Ajax Singleton object of WC_SC_Ajax
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Function to search coupons
*
* @param string $x Search term.
* @param array $post_types Post types.
*/
public function sc_json_search_coupons( $x = '', $post_types = array( 'shop_coupon' ) ) {
global $wpdb;
check_ajax_referer( 'search-coupons', 'security' );
$term = (string) wc_clean( wp_unslash( $_GET['term'] ) ); // phpcs:ignore
if ( empty( $term ) ) {
die();
}
$args = array(
'post_type' => $post_types,
'post_status' => 'publish',
'posts_per_page' => -1,
's' => $term,
'fields' => 'all',
);
$posts = wp_cache_get( 'wc_sc_search_coupon_by_code_' . sanitize_title( $term ), 'woocommerce_smart_coupons' );
if ( false === $posts ) {
$posts = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}posts
WHERE post_type = %s
AND post_title LIKE %s
AND post_status = %s",
'shop_coupon',
$wpdb->esc_like( $term ) . '%',
'publish'
)
);
wp_cache_set( 'wc_sc_search_coupon_by_code_' . sanitize_title( $term ), $posts, 'woocommerce_smart_coupons' );
$this->maybe_add_cache_key( 'wc_sc_search_coupon_by_code_' . sanitize_title( $term ) );
}
$found_products = array();
$all_discount_types = wc_get_coupon_types();
if ( $posts && ! is_scalar( $posts ) ) {
foreach ( $posts as $post ) {
$discount_type = ( ! empty( $post->ID ) ) ? $this->get_post_meta( $post->ID, 'discount_type', true ) : 'fixed_cart';
if ( ! empty( $all_discount_types[ $discount_type ] ) ) {
$discount_type = ' (' . __( 'Type', 'woocommerce-smart-coupons' ) . ': ' . $all_discount_types[ $discount_type ] . ')';
$found_products[ $post->post_title ] = $post->post_title . $discount_type;
}
}
}
wp_send_json( $found_products );
}
/**
* Function to search storewide coupons
*
* @param string $x Search term.
* @param array $post_types Post types.
*/
public function sc_json_search_storewide_coupons( $x = '', $post_types = array( 'shop_coupon' ) ) {
global $wpdb;
check_ajax_referer( 'search-coupons', 'security' );
$term = (string) wc_clean( wp_unslash( $_GET['term'] ) ); // phpcs:ignore
if ( empty( $term ) ) {
die();
}
$found_coupons = array();
$coupon_posts = array();
$posts = wp_cache_get( 'wc_sc_search_storewide_coupon_by_code_' . sanitize_title( $term ), 'woocommerce_smart_coupons' );
if ( false === $posts ) {
$posts = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
"SELECT p.ID,
p.post_title,
pm.meta_key,
pm.meta_value
FROM {$wpdb->posts} AS p
JOIN {$wpdb->postmeta} AS pm
ON (p.ID = pm.post_id AND pm.meta_key IN (%s,%s,%s,%s,%s,%s))
WHERE p.post_type = %s
AND p.post_title LIKE %s
AND p.post_status = %s",
'discount_type',
'coupon_amount',
'date_expires',
'auto_generate_coupon',
'customer_email',
'wc_sc_expiry_time',
'shop_coupon',
$wpdb->esc_like( $term ) . '%',
'publish'
),
ARRAY_A
);
wp_cache_set( 'wc_sc_search_storewide_coupon_by_code_' . sanitize_title( $term ), $posts, 'woocommerce_smart_coupons' );
$this->maybe_add_cache_key( 'wc_sc_search_storewide_coupon_by_code_' . sanitize_title( $term ) );
}
if ( ! empty( $posts ) ) {
foreach ( $posts as $post ) {
$post_id = ( ! empty( $post['ID'] ) ) ? absint( $post['ID'] ) : 0;
$post_title = ( ! empty( $post['post_title'] ) ) ? $post['post_title'] : '';
if ( empty( $post_id ) || empty( $post_title ) ) {
continue;
}
if ( empty( $coupon_posts[ $post_id ] ) || ! is_array( $coupon_posts[ $post_id ] ) ) {
$coupon_posts[ $post_id ] = array();
}
$coupon_posts[ $post_id ]['post_id'] = $post_id;
$coupon_posts[ $post_id ]['post_title'] = $post_title;
switch ( $post['meta_key'] ) {
case 'discount_type':
case 'coupon_amount':
case 'date_expires':
case 'auto_generate_coupon':
case 'wc_sc_expiry_time':
$coupon_posts[ $post_id ][ $post['meta_key'] ] = $post['meta_value']; // phpcs:ignore
break;
case 'customer_email':
$coupon_posts[ $post_id ][ $post['meta_key'] ] = maybe_unserialize( $post['meta_value'] ); // phpcs:ignore
break;
}
}
}
$all_discount_types = wc_get_coupon_types();
if ( ! empty( $coupon_posts ) ) {
foreach ( $coupon_posts as $post_id => $coupon_post ) {
$discount_type = ( ! empty( $coupon_post['discount_type'] ) ) ? $coupon_post['discount_type'] : '';
$coupon_amount = ( ! empty( $coupon_post['coupon_amount'] ) ) ? $coupon_post['coupon_amount'] : 0;
$date_expires = ( ! empty( $coupon_post['date_expires'] ) ) ? absint( $coupon_post['date_expires'] ) : 0;
$wc_sc_expiry_time = ( ! empty( $coupon_post['wc_sc_expiry_time'] ) ) ? absint( $coupon_post['wc_sc_expiry_time'] ) : 0;
$auto_generate_coupon = ( ! empty( $coupon_post['auto_generate_coupon'] ) ) ? $coupon_post['auto_generate_coupon'] : '';
$customer_email = ( ! empty( $coupon_post['customer_email'] ) ) ? $coupon_post['customer_email'] : array();
if ( empty( $discount_type ) || 'smart_coupon' === $discount_type ) {
continue;
}
if ( empty( $coupon_amount ) ) {
continue;
}
if ( ! empty( $date_expires ) ) {
$date_expires += $wc_sc_expiry_time;
if ( time() >= $date_expires ) {
continue;
}
}
if ( 'yes' === $auto_generate_coupon ) {
continue;
}
if ( ! empty( $customer_email ) ) {
continue;
}
if ( ! empty( $all_discount_types[ $discount_type ] ) ) {
/* translators: 1. The coupon code, 2. The discount type */
$found_coupons[ $coupon_post['post_title'] ] = sprintf( __( '%1$s (Type: %2$s)', 'woocommerce-smart-coupons' ), $coupon_post['post_title'], $all_discount_types[ $discount_type ] );
}
}
$found_coupons = apply_filters(
'wc_sc_json_search_storewide_coupons',
$found_coupons,
array(
'source' => $this,
'search_text' => $term,
'posts' => $posts,
'coupon_posts' => $coupon_posts,
)
);
}
wp_send_json( $found_coupons );
}
/**
* JSON Search coupon via ajax
*
* @param string $x Search text.
* @param array $post_types Post types.
*/
public function smart_coupons_json_search( $x = '', $post_types = array( 'shop_coupon' ) ) {
global $wpdb, $store_credit_label;
check_ajax_referer( 'search-coupons', 'security' );
$term = (string) wc_clean( wp_unslash( $_GET['term'] ) ); // phpcs:ignore
if ( empty( $term ) ) {
die();
}
$posts = wp_cache_get( 'wc_sc_shortcode_search_coupon_by_code_' . sanitize_title( $term ), 'woocommerce_smart_coupons' );
if ( false === $posts ) {
$posts = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
"SELECT *
FROM {$wpdb->prefix}posts
WHERE post_type = %s
AND post_title LIKE %s
AND post_status = %s",
'shop_coupon',
$wpdb->esc_like( $term ) . '%',
'publish'
)
);
wp_cache_set( 'wc_sc_shortcode_search_coupon_by_code_' . sanitize_title( $term ), $posts, 'woocommerce_smart_coupons' );
$this->maybe_add_cache_key( 'wc_sc_shortcode_search_coupon_by_code_' . sanitize_title( $term ) );
}
$found_products = array();
$all_discount_types = wc_get_coupon_types();
if ( $posts ) {
foreach ( $posts as $post ) {
$discount_type = ( ! empty( $post->ID ) ) ? $this->get_post_meta( $post->ID, 'discount_type', true ) : 'fixed_cart';
if ( ! empty( $all_discount_types[ $discount_type ] ) ) {
$coupon = new WC_Coupon( $post->post_title );
if ( $this->is_wc_gte_30() ) {
$discount_type = $coupon->get_discount_type();
} else {
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
}
$coupon_amount = $this->get_amount( $coupon );
switch ( $discount_type ) {
case 'smart_coupon':
$coupon_type = ! empty( $store_credit_label['singular'] ) ? ucwords( $store_credit_label['singular'] ) : __( 'Store Credit', 'woocommerce-smart-coupons' );
$coupon_amount = wc_price( $coupon_amount );
break;
case 'fixed_cart':
$coupon_type = __( 'Cart Discount', 'woocommerce-smart-coupons' );
$coupon_amount = wc_price( $coupon_amount );
break;
case 'fixed_product':
$coupon_type = __( 'Product Discount', 'woocommerce-smart-coupons' );
$coupon_amount = wc_price( $coupon_amount );
break;
case 'percent_product':
$coupon_type = __( 'Product Discount', 'woocommerce-smart-coupons' );
$coupon_amount = $coupon_amount . '%';
break;
case 'percent':
$coupon_type = ( $this->is_wc_gte_30() ) ? __( 'Discount', 'woocommerce-smart-coupons' ) : __( 'Cart Discount', 'woocommerce-smart-coupons' );
$coupon_amount = $coupon_amount . '%';
$max_discount = $this->get_post_meta( $post->ID, 'wc_sc_max_discount', true );
if ( ! empty( $max_discount ) && is_numeric( $max_discount ) ) {
/* translators: %s: Maximum coupon discount amount */
$coupon_type .= ' ' . sprintf( __( 'upto %s', 'woocommerce-smart-coupons' ), wc_price( $max_discount ) );
}
break;
default:
$default_coupon_type = ( ! empty( $all_discount_types[ $discount_type ] ) ) ? $all_discount_types[ $discount_type ] : ucwords( str_replace( array( '_', '-' ), ' ', $discount_type ) );
$coupon_type = apply_filters( 'wc_sc_coupon_type', $default_coupon_type, $coupon, $all_discount_types );
$coupon_amount = apply_filters( 'wc_sc_coupon_amount', $coupon_amount, $coupon );
break;
}
$discount_type = ' ( ' . $coupon_amount . ' ' . $coupon_type . ' )';
$discount_type = wp_strip_all_tags( $discount_type );
$found_products[ $post->post_title ] = $post->post_title . ' ' . $discount_type;
}
}
}
if ( ! empty( $found_products ) ) {
echo wp_json_encode( $found_products );
}
die();
}
/**
* Function to Hide Notice Delete After Usage
*/
public function hide_notice_delete_after_usage() {
check_ajax_referer( 'hide-smart-coupons-notice', 'security' );
$current_user_id = get_current_user_id();
update_user_meta( $current_user_id, 'hide_delete_credit_after_usage_notice', 'yes' );
wp_send_json( array( 'message' => 'success' ) );
}
}
}
WC_SC_Ajax::get_instance();

View File

@@ -0,0 +1,633 @@
<?php
/**
* Processing of coupons
*
* @author StoreApps
* @since 3.3.0
* @version 2.1.0
* @package WooCommerce Smart Coupons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Apply_Before_Tax' ) ) {
/**
* Class for applying store credit before tax calculation
*/
class WC_SC_Apply_Before_Tax {
/**
* Variable to hold instance of WC_SC_Apply_Before_Tax
*
* @var $instance
*/
private static $instance = null;
/**
* Store credit left after application on each cart item
*
* @var $sc_credit_left
*/
private $sc_credit_left = array();
/**
* Store credit left after application on each cart item in REST API
*
* @var $sc_api_credit_left
*/
private $sc_api_credit_left = array();
/**
* Remaining total to apply credit
*
* @var $remaining_total_to_apply_credit
*/
private $remaining_total_to_apply_credit = array();
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_order_before_calculate_totals', array( $this, 'order_calculate_discount_amount_before_tax' ), 10, 2 );
add_action( 'woocommerce_checkout_create_order', array( $this, 'cart_set_discount_total' ), 10, 1 );
add_action( 'woocommerce_before_calculate_totals', array( $this, 'cart_calculate_discount_amount' ), 20 );
add_filter( 'woocommerce_coupon_get_discount_amount', array( $this, 'cart_return_discount_amount' ), 20, 5 );
add_filter( 'woocommerce_coupon_custom_discounts_array', array( $this, 'store_credit_discounts_array' ), 10, 2 );
add_filter( 'woocommerce_add_cart_item', array( $this, 'sc_mnm_compat' ), 20, 2 );
add_action( 'woocommerce_after_calculate_totals', array( $this, 'cart_set_total_credit_used' ) );
add_action( 'woocommerce_before_calculate_totals', array( $this, 'cart_reset_credit_left' ), 15 );
add_filter( 'woocommerce_coupon_sort', array( $this, 'change_default_sort_order' ), 20, 2 );
}
/**
* Get single instance of WC_SC_Apply_Before_Tax
*
* @return WC_SC_Apply_Before_Tax Singleton object of WC_SC_Apply_Before_Tax
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name Function to call.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return mixed Result of function call.
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Function to apply store credit before tax calculation for orders that are manually created and updated from backend
*
* @param bool $and_taxes Calc taxes if true.
* @param WC_Order $order Order object.
*/
public function order_calculate_discount_amount_before_tax( $and_taxes, $order ) {
$order_actions = array( 'woocommerce_add_coupon_discount', 'woocommerce_calc_line_taxes', 'woocommerce_save_order_items' );
$order_id = ( $this->is_callable( $order, 'get_id' ) ) ? $order->get_id() : 0;
$post_post_type = ( ! empty( $_POST['post_type'] ) ) ? wc_clean( wp_unslash( $_POST['post_type'] ) ) : ''; // phpcs:ignore
$post_action = ( ! empty( $_POST['action'] ) ) ? wc_clean( wp_unslash( $_POST['action'] ) ) : ''; // phpcs:ignore
$post_type = ( ! empty( $order_id ) && $this->is_hpos() ) ? $this->get_post_type( $order_id ) : $post_post_type;
if ( $order instanceof WC_Order && ( in_array( $post_action, $order_actions, true ) || ( 'shop_order' === $post_type && in_array( $post_action, array( 'edit_order', 'editpost' ), true ) ) ) ) {
if ( ! is_object( $order ) || ! is_callable( array( $order, 'get_id' ) ) ) {
return;
}
if ( empty( $order_id ) ) {
return;
}
$coupons = $order->get_items( 'coupon' );
$order_items = $order->get_items( 'line_item' );
if ( empty( $order_items ) && empty( $coupons ) ) {
return;
}
foreach ( $coupons as $item_id => $item ) {
$coupon_code = ( is_object( $item ) && is_callable( array( $item, 'get_name' ) ) ) ? $item->get_name() : $item['name'];
if ( empty( $coupon_code ) ) {
continue;
}
$coupon = new WC_Coupon( $coupon_code );
$discount_type = $coupon->get_discount_type();
if ( 'smart_coupon' === $discount_type ) {
$sc_include_tax = $this->is_store_credit_include_tax();
$smart_coupons_contribution = $this->get_post_meta( $order_id, 'smart_coupons_contribution', true, true );
$smart_coupons_contribution = ( ! empty( $smart_coupons_contribution ) ) ? $smart_coupons_contribution : array();
$discount_amount = ( is_object( $item ) && is_callable( array( $item, 'get_discount' ) ) ) ? $item->get_discount() : $this->get_order_item_meta( $item_id, 'discount_amount', true, true );
$discount_amount_tax = ( is_object( $item ) && is_callable( array( $item, 'get_discount_tax' ) ) ) ? $item->get_discount_tax() : $this->get_order_item_meta( $item_id, 'discount_amount_tax', true, true );
if ( is_array( $smart_coupons_contribution ) && count( $smart_coupons_contribution ) > 0 && array_key_exists( $coupon_code, $smart_coupons_contribution ) ) {
// If store credit discount is inclusive of tax then remove discount given tax from Smart Coupons' contribution.
if ( 'yes' === $sc_include_tax && ! empty( $discount_amount_tax ) ) {
$new_discount = $smart_coupons_contribution[ $coupon_code ] - $discount_amount_tax;
} else {
$new_discount = $smart_coupons_contribution[ $coupon_code ];
}
if ( is_object( $item ) && is_callable( array( $item, 'set_discount' ) ) ) {
$item->set_discount( $new_discount );
} else {
$item['discount_amount'] = $new_discount;
}
} elseif ( ! empty( $discount_amount ) ) {
if ( is_object( $item ) && is_callable( array( $item, 'set_discount' ) ) ) {
$item->set_discount( $discount_amount );
} else {
$item['discount_amount'] = $discount_amount;
}
// If discount includes tax then Smart Coupons contribution is sum of discount on product price and discount on tax.
if ( 'yes' === $sc_include_tax && ! empty( $discount_amount_tax ) ) {
$smart_coupons_contribution[ $coupon_code ] = $discount_amount + $discount_amount_tax;
} else {
$smart_coupons_contribution[ $coupon_code ] = $discount_amount;
}
$this->update_post_meta( $order_id, 'smart_coupons_contribution', $smart_coupons_contribution, true );
} else {
$coupon_amount = $this->get_amount( $coupon, true, $order );
$coupon_product_ids = $coupon->get_product_ids();
$coupon_category_ids = $coupon->get_product_categories();
$subtotal = 0;
$items_to_apply_credit = array();
if ( count( $coupon_product_ids ) > 0 || count( $coupon_category_ids ) > 0 ) {
foreach ( $order_items as $order_item_id => $order_item ) {
$product_category_ids = wc_get_product_cat_ids( $order_item['product_id'] );
if ( count( $coupon_product_ids ) > 0 && count( $coupon_category_ids ) > 0 ) {
if ( ( in_array( $order_item['product_id'], $coupon_product_ids, true ) || in_array( $order_item['variation_id'], $coupon_product_ids, true ) ) && count( array_intersect( $product_category_ids, $coupon_category_ids ) ) > 0 ) {
$items_to_apply_credit[] = $order_item_id;
}
} else {
if ( in_array( $order_item['product_id'], $coupon_product_ids, true ) || in_array( $order_item['variation_id'], $coupon_product_ids, true ) || count( array_intersect( $product_category_ids, $coupon_category_ids ) ) > 0 ) {
$items_to_apply_credit[] = $order_item_id;
}
}
}
} else {
$items_to_apply_credit = array_keys( $order_items );
}
$subtotal = array_sum( array_map( array( $this, 'sc_get_order_subtotal' ), $items_to_apply_credit ) );
if ( $subtotal <= 0 ) {
continue;
}
$store_credit_used = 0;
foreach ( $items_to_apply_credit as $order_item_id ) {
$order_item = $order_items[ $order_item_id ];
$discounting_amount = $order_item->get_total();
// If discount include tax then add item tax to discounting amount to allow discount calculation on tax also.
if ( 'yes' === $sc_include_tax ) {
$item_tax = ( is_callable( array( $order, 'get_line_tax' ) ) ) ? $order->get_line_tax( $order_item ) : 0;
$discounting_amount += $item_tax;
}
$quantity = $order_item->get_quantity();
$discount = $this->sc_get_discounted_price( $discounting_amount, $quantity, $subtotal, $coupon_amount );
$discount *= $quantity;
$order_item->set_total( $discounting_amount - $discount );
$store_credit_used += $discount;
}
if ( is_object( $item ) && is_callable( array( $item, 'set_discount' ) ) ) {
$item->set_discount( $store_credit_used );
} else {
$item['discount_amount'] = $store_credit_used;
}
$smart_coupons_contribution[ $coupon_code ] = $store_credit_used;
$this->update_post_meta( $order_id, 'smart_coupons_contribution', $smart_coupons_contribution, true );
}
$order->sc_total_credit_used = $smart_coupons_contribution;
}
}
}
}
/**
* Function to calculate subtotal of items in order which is necessary for applying store credit before tax calculation
*
* @param int $order_item_id Item ID.
* @return float $subtotal
*/
private function sc_get_order_subtotal( $order_item_id ) {
$order_item = WC_Order_Factory::get_order_item( $order_item_id );
$subtotal = $order_item->get_total();
$prices_include_tax = wc_prices_include_tax();
// Get global setting for whether store credit discount is inclusive of tax or not.
$sc_include_tax = get_option( 'woocommerce_smart_coupon_include_tax', 'no' );
// If prices are inclusive of tax and discount amount is also inclusive of tax then add item tax in subtotal to handle discount calculation correctly.
if ( true === $prices_include_tax && 'yes' === $sc_include_tax ) {
$subtotal += $order_item->get_total_tax();
}
return $subtotal;
}
/**
* Function to update_discount_total for an order
*
* @param WC_Order $order Order object.
* @param float $total_credit_used Total store credit used.
*/
public function update_discount_total( $order = '', $total_credit_used = 0 ) {
if ( $order instanceof WC_Order ) {
$discount_total = $order->get_discount_total();
$sc_credit_used = min( $discount_total, $total_credit_used );
$order->set_discount_total( $discount_total - $sc_credit_used );
}
}
/**
* Function to set discount total for a new order
*
* @param WC_Order $order Order object.
*/
public function cart_set_discount_total( $order ) {
if ( isset( WC()->cart->smart_coupon_credit_used ) && is_array( WC()->cart->smart_coupon_credit_used ) && count( WC()->cart->smart_coupon_credit_used ) > 0 ) {
$total_credit_used = array_sum( WC()->cart->smart_coupon_credit_used );
$this->update_discount_total( $order, $total_credit_used );
}
}
/**
* Function to apply store credit before tax calculation for cart items
*/
public function cart_calculate_discount_amount() {
$cart = ( isset( WC()->cart ) ) ? WC()->cart : '';
if ( $cart instanceof WC_Cart ) {
$cart_contents = WC()->cart->get_cart();
$coupons = $cart->get_coupons();
if ( ! empty( $coupons ) ) {
$items_to_apply_credit = array();
foreach ( $coupons as $coupon_code => $coupon ) {
$discount_type = $coupon->get_discount_type();
if ( 'smart_coupon' === $discount_type ) {
$coupon_product_ids = $coupon->get_product_ids();
$coupon_category_ids = $coupon->get_product_categories();
if ( count( $coupon_product_ids ) > 0 || count( $coupon_category_ids ) > 0 ) {
foreach ( $cart_contents as $cart_item_key => $cart_item ) {
$product_category_ids = wc_get_product_cat_ids( $cart_item['product_id'] );
if ( count( $coupon_product_ids ) > 0 && count( $coupon_category_ids ) > 0 ) {
if ( ( in_array( $cart_item['product_id'], $coupon_product_ids, true ) || in_array( $cart_item['variation_id'], $coupon_product_ids, true ) ) && count( array_intersect( $product_category_ids, $coupon_category_ids ) ) > 0 ) {
$items_to_apply_credit[ $coupon_code ][] = $cart_item_key;
}
} else {
if ( in_array( $cart_item['product_id'], $coupon_product_ids, true ) || in_array( $cart_item['variation_id'], $coupon_product_ids, true ) || count( array_intersect( $product_category_ids, $coupon_category_ids ) ) > 0 ) {
$items_to_apply_credit[ $coupon_code ][] = $cart_item_key;
}
}
}
} else {
$items_to_apply_credit[ $coupon_code ] = array_keys( $cart_contents );
}
}
}
if ( ! empty( $items_to_apply_credit ) ) {
WC()->cart->sc_items_to_apply_credit = $items_to_apply_credit;
}
}
}
}
/**
* Get discount amount for a cart item.
*
* @param float $discount Amount this coupon has discounted.
* @param float $discounting_amount Amount the coupon is being applied to.
* @param array|null $cart_item Cart item being discounted if applicable.
* @param bool $single True if discounting a single qty item, false if its the line.
* @param WC_Coupon $coupon Coupon object.
* @return float $discount
*/
public function cart_return_discount_amount( $discount, $discounting_amount, $cart_item, $single, $coupon ) {
if ( ! is_object( $coupon ) || ! is_a( $coupon, 'WC_Coupon' ) ) {
return $discount;
}
$discount_type = is_callable( array( $coupon, 'get_discount_type' ) ) ? $coupon->get_discount_type() : '';
if ( 'smart_coupon' !== $discount_type ) {
return $discount;
}
$coupon_code = is_callable( array( $coupon, 'get_code' ) ) ? $coupon->get_code() : '';
if ( is_object( $cart_item ) && is_a( $cart_item, 'WC_Order_Item_Product' ) ) {
return $this->calculate_discount_amount_for_rest_api( $discount, $discounting_amount, $cart_item, $single, $coupon );
}
$coupon_amount = $this->get_amount( $coupon, true );
$product = isset( $cart_item['data'] ) ? $cart_item['data'] : array();
$quantity = $cart_item['quantity'];
// Compatibility for WC version < 3.2.0.
if ( ! isset( $cart_item['key'] ) ) {
$product_id = ( ! empty( $cart_item['variation_id'] ) ) ? $cart_item['variation_id'] : $cart_item['product_id'];
foreach ( WC()->cart->cart_contents as $key => $cart_data ) {
$cart_data_product_id = ( ! empty( $cart_data['variation_id'] ) ) ? $cart_data['variation_id'] : $cart_data['product_id'];
if ( $product_id === $cart_data_product_id ) {
$cart_item['key'] = $key;
}
}
}
$prices_include_tax = ( 'incl' === get_option( 'woocommerce_tax_display_cart' ) ) ? true : false;
if ( true === $prices_include_tax ) {
$sc_include_tax = get_option( 'woocommerce_smart_coupon_include_tax', 'no' );
if ( 'no' === $sc_include_tax ) {
$discounting_amount = $cart_item['line_subtotal'] / $quantity;
}
}
$items_to_apply_credit = isset( WC()->cart->sc_items_to_apply_credit ) ? WC()->cart->sc_items_to_apply_credit : array();
if ( ! empty( $items_to_apply_credit ) && is_array( $items_to_apply_credit ) && array_key_exists( $coupon_code, $items_to_apply_credit ) && in_array( $cart_item['key'], $items_to_apply_credit[ $coupon_code ], true ) ) {
$credit_left = isset( $this->sc_credit_left[ $coupon_code ] ) ? $this->sc_credit_left[ $coupon_code ] : $coupon_amount;
$total_discounting_amount = $discounting_amount * $quantity;
if ( isset( $this->remaining_total_to_apply_credit[ $cart_item['key'] ] ) ) {
$total_discounting_amount = wc_remove_number_precision( $this->remaining_total_to_apply_credit[ $cart_item['key'] ] );
}
$applied_discount = min( $total_discounting_amount, $credit_left );
$this->sc_credit_left[ $coupon_code ] = ( $total_discounting_amount < $credit_left ) ? $credit_left - $total_discounting_amount : 0;
$discount = $applied_discount / $quantity;
}
return $discount;
}
/**
* Calculate discount amount for REST API and Order created via backend.
*
* @param float $discount Amount this coupon has discounted.
* @param float $discounting_amount Amount the coupon is being applied to.
* @param WC_Order_Item_Product $cart_item Object.
* @param bool $single True if discounting a single qty item, false if its the line.
* @param WC_Coupon $coupon Object.
* @return float|int|mixed
*/
public function calculate_discount_amount_for_rest_api( $discount = 0, $discounting_amount = 0, $cart_item = object, $single = false, $coupon = object ) {
if ( ! is_object( $coupon ) || ! is_a( $coupon, 'WC_Coupon' ) ) {
return $discount;
}
if ( ! is_object( $cart_item ) || ! is_a( $cart_item, 'WC_Order_Item_Product' ) ) {
return $discount;
}
$quantity = ( is_callable( array( $cart_item, 'get_quantity' ) ) ) ? $cart_item->get_quantity() : 1;
$item_id = ( is_callable( array( $cart_item, 'get_id' ) ) ) ? $cart_item->get_id() : 0;
$product_subtotal = ( is_callable( array( $cart_item, 'get_subtotal' ) ) ) ? $cart_item->get_subtotal() : 0;
$order = ( is_callable( array( $cart_item, 'get_order' ) ) ) ? $cart_item->get_order() : null;
$coupon_code = ( is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
$discount_type = ( is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
if ( 'smart_coupon' !== $discount_type ) {
return $discount;
}
$smart_coupons_contribution = ( is_callable( array( $order, 'get_meta' ) ) ) ? $order->get_meta( 'smart_coupons_contribution' ) : array();
if ( isset( $this->sc_api_credit_left[ $coupon_code ]['items'] ) && ! empty( $this->sc_api_credit_left[ $coupon_code ]['items'][ $item_id ] ) ) {
return $this->sc_api_credit_left[ $coupon_code ]['items'][ $item_id ];
}
$coupon_amount = is_array( $smart_coupons_contribution ) && isset( $smart_coupons_contribution[ $coupon_code ] ) ? $smart_coupons_contribution[ $coupon_code ] : (float) $this->get_amount( $coupon, true, $order );
// isset is required here to confirm that store credit was used but now it is empty.
if ( $coupon_amount < 1 || ( isset( $this->sc_api_credit_left[ $coupon_code ]['credit_left'] ) && empty( $this->sc_api_credit_left[ $coupon_code ]['credit_left'] ) ) ) {
return $discount;
}
$prices_include_tax = ( 'yes' === get_option( 'woocommerce_prices_include_tax' ) ) ? true : false;
if ( true === $prices_include_tax ) {
$sc_include_tax = get_option( 'woocommerce_smart_coupon_include_tax', 'no' );
if ( 'no' === $sc_include_tax ) {
$discounting_amount = $product_subtotal / $quantity;
}
}
$credit_left = ( ! empty( $this->sc_api_credit_left ) && isset( $this->sc_api_credit_left[ $coupon_code ]['credit_left'] ) ) ? $this->sc_api_credit_left[ $coupon_code ]['credit_left'] : $coupon_amount;
if ( $credit_left > 0 ) {
$total_credit_already_applied_current_item = is_array( $this->sc_api_credit_left ) && count( $this->sc_api_credit_left ) > 0 ? (float) array_sum( wp_list_pluck( array_column( array_values( $this->sc_api_credit_left ), 'items' ), $item_id ) ) : 0;
if ( $single ) {
$discount = min( $quantity * ( $discounting_amount - $total_credit_already_applied_current_item ), $credit_left );
} else {
$discount = min( ( $discounting_amount - ( $total_credit_already_applied_current_item * $quantity ) ), $credit_left );
}
$credit_left -= $discount;
$this->sc_api_credit_left[ $coupon_code ]['credit_left'] = $credit_left;
$discount = (float) $discount / $quantity;
}
// Note*: We always store discount credit inside sc_api_credit_left as discounting_amount not line total.
$this->sc_api_credit_left[ $coupon_code ]['items'][ $item_id ] = $discount;
return $single ? $discount : $discount * $quantity;
}
/**
* Discount details for store credit
*
* @param array $discounts The discount details.
* @param WC_Coupon $coupon The coupon object.
* @return array
*/
public function store_credit_discounts_array( $discounts = array(), $coupon = null ) {
$cart = ( isset( WC()->cart ) ) ? WC()->cart : '';
if ( $cart instanceof WC_Cart ) {
$cart_contents = ( is_object( WC()->cart ) && is_callable( array( WC()->cart, 'get_cart' ) ) ) ? WC()->cart->get_cart() : array();
if ( ! empty( $cart_contents ) ) {
$discount_type = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
if ( 'smart_coupon' === $discount_type ) {
$prices_include_tax = ( 'incl' === get_option( 'woocommerce_tax_display_cart' ) ) ? true : false;
if ( true === $prices_include_tax ) {
$sc_include_tax = get_option( 'woocommerce_smart_coupon_include_tax', 'no' );
if ( 'no' === $sc_include_tax ) {
if ( ! empty( $discounts ) ) {
foreach ( $discounts as $item_key => $discount ) {
$line_subtotal = wc_round_discount( wc_add_number_precision( $cart_contents[ $item_key ]['line_subtotal'] ), 0 );
$line_subtotal = ( isset( $this->remaining_total_to_apply_credit[ $item_key ] ) ) ? min( $this->remaining_total_to_apply_credit[ $item_key ], $line_subtotal ) : $line_subtotal;
$discount = min( $discount, $line_subtotal );
$discounts [ $item_key ] = $discount;
$this->remaining_total_to_apply_credit[ $item_key ] = $line_subtotal - $discount;
}
}
}
}
}
}
}
return $discounts;
}
/**
* Set smart coupon credit used
*/
public function cart_set_total_credit_used() {
$coupon_discount_totals = ( is_callable( array( 'WC_Cart', 'get_coupon_discount_totals' ) ) ) ? WC()->cart->get_coupon_discount_totals() : WC()->cart->coupon_discount_amounts;
$coupon_discount_tax_totals = ( is_callable( array( 'WC_Cart', 'get_coupon_discount_tax_totals' ) ) ) ? WC()->cart->get_coupon_discount_tax_totals() : WC()->cart->coupon_discount_tax_amounts;
$sc_total_credit_used = array();
if ( ! empty( $coupon_discount_totals ) && is_array( $coupon_discount_totals ) && count( $coupon_discount_totals ) > 0 ) {
foreach ( $coupon_discount_totals as $coupon_code => $total ) {
$coupon = new WC_Coupon( $coupon_code );
$discount_type = $coupon->get_discount_type();
if ( 'smart_coupon' === $discount_type ) {
$sc_total_credit_used[ $coupon_code ] = $total;
if ( ! empty( $coupon_discount_tax_totals[ $coupon_code ] ) ) {
$sc_include_tax = $this->is_store_credit_include_tax();
if ( 'yes' === $sc_include_tax ) {
$sc_total_credit_used[ $coupon_code ] += $coupon_discount_tax_totals[ $coupon_code ];
} else {
$prices_include_tax = ( 'incl' === get_option( 'woocommerce_tax_display_cart' ) ) ? true : false;
if ( true === $prices_include_tax ) {
$apply_before_tax = get_option( 'woocommerce_smart_coupon_apply_before_tax', 'no' );
if ( 'yes' === $apply_before_tax ) {
$_sc_include_tax = get_option( 'woocommerce_smart_coupon_include_tax', 'no' );
if ( 'no' === $_sc_include_tax ) {
$sc_total_credit_used[ $coupon_code ] += $coupon_discount_tax_totals[ $coupon_code ];
}
}
}
}
}
}
}
}
if ( ! empty( $sc_total_credit_used ) ) {
WC()->cart->smart_coupon_credit_used = $sc_total_credit_used;
}
}
/**
* Function to calculate discount amount for an item
*
* @param float $discounting_amount Amount the coupon is being applied to.
* @param int $quantity Item quantity.
* @param float $subtotal Cart/Order subtotal.
* @param float $coupon_amount Coupon amount.
* @return float $discount
*/
public function sc_get_discounted_price( $discounting_amount = 0, $quantity = 1, $subtotal = 0, $coupon_amount = 0 ) {
$discount = 0;
$discounting_amount = $discounting_amount / $quantity;
$discount_percent = ( $discounting_amount * $quantity ) / $subtotal;
$discount = ( $coupon_amount * $discount_percent ) / $quantity;
$discount = min( $discount, $discounting_amount );
return $discount;
}
/**
* Function to add cart item key for MNM child items.
* This was need because MNM child items didn't had cart item key inside $cart_item_data array and the
* function WC_SC_Apply_Before_Tax::cart_return_discount_amount() uses cart item key to set discount amount.
*
* @param array $cart_item_data Cart item data.
* @param string $cart_item_key Cart item key.
* @return float $cart_item_data
*/
public function sc_mnm_compat( $cart_item_data, $cart_item_key ) {
if ( ! empty( $cart_item_data['mnm_container'] ) ) {
$cart_item_data['key'] = $cart_item_key;
}
return $cart_item_data;
}
/**
* Reset credit left to the defaults.
*/
public function cart_reset_credit_left() {
$this->sc_credit_left = array();
$this->sc_api_credit_left = array();
$this->remaining_total_to_apply_credit = array();
}
/**
* Function to override smart coupon sequence order defauly by woocommerce.
*
* @param number $sort order sequence number.
* @param object $coupon object of Coupon.
* @return number $sort
*/
public function change_default_sort_order( $sort = 0, $coupon = null ) {
if ( is_admin() || ! $coupon instanceof WC_Coupon || is_null( $coupon ) || ! is_callable( array( $coupon, 'get_discount_type' ) ) || ( is_callable( array( $coupon, 'get_discount_type' ) ) && $coupon->get_discount_type() !== 'smart_coupon' ) ) {
return $sort;
}
// Allow plugins to override the default order.
return apply_filters( 'wc_sc_coupon_sort_order', 4, $coupon );
}
}
}
WC_SC_Apply_Before_Tax::get_instance();

View File

@@ -0,0 +1,751 @@
<?php
/**
* Auto apply coupon
*
* @author StoreApps
* @since 4.6.0
* @version 2.8.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Auto_Apply_Coupon' ) ) {
/**
* Class for handling coupons applied via URL
*/
class WC_SC_Auto_Apply_Coupon {
/**
* Variable to hold instance of WC_SC_Auto_Apply_Coupon
*
* @var $instance
*/
private static $instance = null;
/**
* Variable to hold coupon notices
*
* @var $coupon_notices
*/
private $coupon_notices = array();
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_coupon_options', array( $this, 'usage_restriction' ), 10, 2 );
add_action( 'woocommerce_coupon_options_save', array( $this, 'process_meta' ), 10, 2 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'wc_sc_process_coupon_meta_value_for_import', array( $this, 'process_coupon_meta_value_for_import' ), 10, 2 );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_action( 'wp_loaded', array( $this, 'handle_auto_apply_hooks' ), 15 );
add_action( 'woocommerce_cart_calculate_fees', array( $this, 'remove_coupon_if_zero' ), 10, 1 );
}
/**
* Get single instance of WC_SC_Auto_Apply_Coupon
*
* @return WC_SC_Auto_Apply_Coupon Singleton object of WC_SC_Auto_Apply_Coupon
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Display field for auto apply coupon
*
* @param integer $coupon_id The coupon id.
* @param WC_Coupon $coupon The coupon object.
*/
public function usage_restriction( $coupon_id = 0, $coupon = null ) {
?>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
const showHideAutoApplyCouponField = () => {
let discountType = document.querySelector('select#discount_type').value;
let autoApplyField = document.querySelector('.wc_sc_auto_apply_coupon_field');
autoApplyField.style.display = ( 'smart_coupon' === discountType ) ? 'none' : 'block';
};
showHideAutoApplyCouponField();
document.querySelector('select#discount_type').addEventListener('change', () => {
showHideAutoApplyCouponField();
});
});
</script>
<div class="options_group smart-coupons-field">
<?php
$is_allow_auto_apply = $this->sc_get_option( 'wc_sc_allow_auto_apply', 'yes' );
if ( 'yes' === $is_allow_auto_apply ) {
woocommerce_wp_checkbox(
array(
'id' => 'wc_sc_auto_apply_coupon',
'label' => __( 'Auto apply?', 'woocommerce-smart-coupons' ),
'description' => __( 'When checked, this coupon will be applied automatically, if it is valid. If enabled in more than 5 coupons, only 5 coupons will be applied automatically, rest will be ignored.', 'woocommerce-smart-coupons' ),
)
);
}
?>
</div>
<?php
}
/**
* Save auto apply coupon in meta
*
* @param Integer $post_id The coupon post ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function process_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$is_callable_coupon_update_meta = $this->is_callable( $coupon, 'update_meta_data' ) && $this->is_callable( $coupon, 'save' );
// Get list of ids of coupons to auto apply.
$auto_apply_coupon_ids = get_option( 'wc_sc_auto_apply_coupon_ids', array() );
$auto_apply_coupon_ids = ( empty( $auto_apply_coupon_ids ) || ! is_array( $auto_apply_coupon_ids ) ) ? array() : $auto_apply_coupon_ids;
$auto_apply_coupon_ids = array_map( 'absint', $auto_apply_coupon_ids );
$post_id = absint( $post_id );
if ( isset( $_POST['wc_sc_auto_apply_coupon'] ) && isset( $_POST['discount_type'] ) && 'smart_coupon' !== wc_clean( wp_unslash( $_POST['discount_type'] ) ) ) { // phpcs:ignore
$auto_apply_coupon = wc_clean( wp_unslash( $_POST['wc_sc_auto_apply_coupon'] ) ); // phpcs:ignore
if ( true === $is_callable_coupon_update_meta ) {
$coupon->update_meta_data( 'wc_sc_auto_apply_coupon', $auto_apply_coupon );
$coupon->save();
} else {
$this->update_post_meta( $post_id, 'wc_sc_auto_apply_coupon', $auto_apply_coupon );
}
// Add coupon id to auto apply coupon list if haven't added already.
if ( is_array( $auto_apply_coupon_ids ) && ! in_array( $post_id, $auto_apply_coupon_ids, true ) ) {
$auto_apply_coupon_ids[] = $post_id;
}
} else {
if ( true === $is_callable_coupon_update_meta ) {
$coupon->update_meta_data( 'wc_sc_auto_apply_coupon', 'no' );
$coupon->save();
} else {
$this->update_post_meta( $post_id, 'wc_sc_auto_apply_coupon', 'no' );
}
// Remove coupon id from auto apply coupon list if auto apply is disabled.
if ( is_array( $auto_apply_coupon_ids ) && in_array( $post_id, $auto_apply_coupon_ids, true ) ) {
$auto_apply_coupon_ids = array_diff( $auto_apply_coupon_ids, array( $post_id ) );
}
}
update_option( 'wc_sc_auto_apply_coupon_ids', $auto_apply_coupon_ids, 'no' );
}
/**
* Add meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$headers['wc_sc_auto_apply_coupon'] = __( 'Auto apply?', 'woocommerce-smart-coupons' );
return $headers;
}
/**
* Post meta defaults for auto apply coupon meta
*
* @param array $defaults Existing postmeta defaults.
* @return array $defaults Modified postmeta defaults
*/
public function postmeta_defaults( $defaults = array() ) {
$defaults['wc_sc_auto_apply_coupon'] = '';
return $defaults;
}
/**
* Add auto apply coupon's meta with value in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array $data Modified row data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
if ( isset( $post['discount_type'] ) && 'smart_coupon' !== $post['discount_type'] ) {
$data['wc_sc_auto_apply_coupon'] = ( isset( $post['wc_sc_auto_apply_coupon'] ) ) ? $post['wc_sc_auto_apply_coupon'] : '';
}
return $data;
}
/**
* Process coupon meta value for import
*
* @param mixed $meta_value The meta value.
* @param array $args Additional Arguments.
* @return mixed $meta_value
*/
public function process_coupon_meta_value_for_import( $meta_value = null, $args = array() ) {
$discount_type = isset( $args['discount_type'] ) ? $args['discount_type'] : '';
if ( 'smart_coupon' !== $discount_type && ! empty( $args['meta_key'] ) && 'wc_sc_auto_apply_coupon' === $args['meta_key'] ) {
$auto_apply_coupon = $meta_value;
if ( 'yes' === $auto_apply_coupon ) {
$auto_apply_coupon_ids = get_option( 'wc_sc_auto_apply_coupon_ids', array() );
$auto_apply_coupon_ids = ( empty( $auto_apply_coupon_ids ) || ! is_array( $auto_apply_coupon_ids ) ) ? array() : $auto_apply_coupon_ids;
$auto_apply_coupon_ids = array_map( 'absint', $auto_apply_coupon_ids );
$coupon_id = ( isset( $args['post']['post_id'] ) ) ? absint( $args['post']['post_id'] ) : 0;
if ( ! empty( $coupon_id ) && ! in_array( $coupon_id, $auto_apply_coupon_ids, true ) ) {
$auto_apply_coupon_ids[] = $coupon_id;
update_option( 'wc_sc_auto_apply_coupon_ids', $auto_apply_coupon_ids, 'no' );
}
}
}
return $meta_value;
}
/**
* Make meta data of auto apply coupon meta protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected = false, $meta_key = '', $meta_type = '' ) {
if ( 'wc_sc_auto_apply_coupon' === $meta_key ) {
return true;
}
return $protected;
}
/**
* Get auto applied coupons
*
* @since 4.27.0
* @return array
*/
public function get_auto_applied_coupons() {
$coupons = ( is_object( WC()->session ) && is_callable( array( WC()->session, 'get' ) ) ) ? WC()->session->get( 'wc_sc_auto_applied_coupons' ) : array();
$coupons = ( ! empty( $coupons ) && is_array( $coupons ) ) ? array_filter( array_unique( $coupons ) ) : array();
return apply_filters( 'wc_sc_' . __FUNCTION__, $coupons, array( 'source' => $this ) );
}
/**
* Add auto applied coupon to WC session
*
* @since 4.27.0
* @param string $coupon_code Coupon Code.
*/
public function set_auto_applied_coupon( $coupon_code = '' ) {
if ( ! empty( $coupon_code ) ) {
$coupons = $this->get_auto_applied_coupons();
// Check if auto applied coupons are not empty.
if ( ! empty( $coupons ) && is_array( $coupons ) ) {
$coupons[] = $coupon_code;
} else {
$coupons = array( $coupon_code );
}
if ( is_object( WC()->session ) && is_callable( array( WC()->session, 'set' ) ) ) {
WC()->session->set( 'wc_sc_auto_applied_coupons', $coupons );
}
}
}
/**
* Remove an auto applied coupon from WC session
*
* @since 4.31.0
* @param string $coupon_code Coupon Code.
*/
public function unset_auto_applied_coupon( $coupon_code = '' ) {
if ( ! empty( $coupon_code ) ) {
$update = false;
$coupons = $this->get_auto_applied_coupons();
// Check if auto applied coupons are not empty.
if ( ! empty( $coupons ) && in_array( $coupon_code, $coupons, true ) ) {
$coupons = array_diff( $coupons, array( $coupon_code ) );
$update = true;
}
if ( true === $update && is_object( WC()->session ) && is_callable( array( WC()->session, 'set' ) ) ) {
$coupons = array_values( array_filter( $coupons ) );
WC()->session->set( 'wc_sc_auto_applied_coupons', $coupons );
}
}
}
/**
* Reset cart session data.
*
* @since 4.27.0
*/
public function reset_auto_applied_coupons_session() {
if ( is_object( WC()->session ) && is_callable( array( WC()->session, 'set' ) ) ) {
WC()->session->set( 'wc_sc_auto_applied_coupons', null );
}
}
/**
* Runs after a coupon is removed
*
* @since 4.31.0
* @param string $coupon_code The coupon code.
* @return void
*/
public function wc_sc_removed_coupon( $coupon_code = '' ) {
$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore
$is_automatic = true;
if ( ! empty( $backtrace ) ) {
foreach ( $backtrace as $trace ) {
if (
isset( $trace['file'] ) &&
(
false !== strpos( $trace['file'], 'StoreApi/Routes/V1/CartRemoveCoupon.php' ) ||
( ! empty( $trace['function'] ) && 'remove_coupon' === $trace['function'] && ! empty( $trace['class'] ) && 'WC_AJAX' === $trace['class'] )
)
) {
if ( false !== strpos( $trace['file'], 'StoreApi/Routes/V1/CartRemoveCoupon.php' ) ) {
// Call auto_apply_coupons() if removal is from StoreApi/Routes/V1/CartRemoveCoupon.php.
$this->auto_apply_coupons();
return; // Exit function after calling auto_apply_coupons().
}
// Coupon was removed by the user.
$is_automatic = false;
break; // Exit loop once the user removal is identified.
}
}
}
if ( $is_automatic ) {
$this->unset_auto_applied_coupon( $coupon_code );
}
}
/**
* Check if auto apply coupon allowed in the cart
*
* @since 4.27.0
* @return bool.
*/
public function is_allow_auto_apply_coupons() {
$auto_applied_coupons = $this->get_auto_applied_coupons();
$auto_applied_coupons_count = ! empty( $auto_applied_coupons ) && is_array( $auto_applied_coupons ) ? count( $auto_applied_coupons ) : 0;
$max_auto_apply_coupons_limit = apply_filters( 'wc_sc_max_auto_apply_coupons_limit', get_option( 'wc_sc_max_auto_apply_coupons_limit', 5 ), array( 'source' => $this ) );
return apply_filters(
'wc_sc_' . __FUNCTION__,
$auto_applied_coupons_count < $max_auto_apply_coupons_limit,
array(
'source' => $this,
'auto_applied_coupons' => $auto_applied_coupons,
)
);
}
/**
* Check if the auto apply removable
*
* @since 4.27.0
* @param string $coupon_code Coupon Code.
* @return bool.
*/
public function is_auto_apply_coupon_removable( $coupon_code = '' ) {
return apply_filters(
'wc_sc_' . __FUNCTION__,
get_option( 'wc_sc_auto_apply_coupon_removable', 'yes' ),
array(
'source' => $this,
'coupon_code' => $coupon_code,
)
);
}
/**
* Check if the coupon is applied through auto apply
*
* @since 4.27.0
* @param string $coupon_code Coupon Code.
* @return bool.
*/
public function is_coupon_applied_by_auto_apply( $coupon_code = '' ) {
if ( ! empty( $coupon_code ) ) {
$applied_coupons = $this->get_auto_applied_coupons();
if ( ! empty( $applied_coupons ) && is_array( $applied_coupons ) && in_array( $coupon_code, $applied_coupons, true ) ) {
return true;
}
}
return false;
}
/**
* Check if coupon is applicable for auto apply
*
* @since 4.26.0
* @param WC_Coupon $coupon WooCommerce coupon object.
* @return bool
*/
public function is_coupon_valid_for_auto_apply( $coupon = null ) {
$valid = false;
if ( is_object( $coupon ) && $coupon instanceof WC_Coupon ) {
if ( $this->is_wc_gte_30() ) {
$coupon_code = is_callable( array( $coupon, 'get_code' ) ) ? $coupon->get_code() : '';
$discount_type = is_callable( array( $coupon, 'get_discount_type' ) ) ? $coupon->get_discount_type() : '';
$is_auto_generate_coupon = is_callable( array( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'auto_generate_coupon' ) : 'no';
$is_disable_email_restrict = is_callable( array( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'sc_disable_email_restriction' ) : 'no';
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
$discount_type = get_post_meta( $coupon_id, 'discount_type', true );
$is_auto_generate_coupon = get_post_meta( $coupon_id, 'auto_generate_coupon', true );
$is_disable_email_restrict = get_post_meta( $coupon_id, 'sc_disable_email_restriction', true );
}
$is_removable = $this->is_auto_apply_coupon_removable( $coupon_code );
$is_auto_applied = $this->is_coupon_applied_by_auto_apply( $coupon_code );
/**
* Validate coupon for auto apply if
*
* Discount type is not smart_coupon.
* Auto generate is not enabled.
* Coupon should not be auto applied OR auto applied coupon should not be removable.
* Coupon code is valid.
*/
$valid = 'smart_coupon' !== $discount_type
&& 'yes' !== $is_auto_generate_coupon
&& ( ! $is_auto_applied || 'yes' !== $is_removable )
&& $this->is_valid( $coupon );
}
return apply_filters(
'wc_sc_' . __FUNCTION__,
$valid,
array(
'coupon_obj' => $coupon,
'source' => $this,
)
);
}
/**
* Function to apply coupons automatically.
*
* TODO: IF we need another variable for removed coupons;
* There will be 2 session variables: wc_sc_auto_applied_coupons and wc_sc_removed_auto_applied_coupons.
* Whenever a coupon will be auto-applied, it'll be stored in wc_sc_auto_applied_coupons.
* Whenever a coupon will be removed, it'll be moved from wc_sc_auto_applied_coupons to wc_sc_removed_auto_applied_coupons.
* And before applying an auto-apply coupon, it'll be made sure that the coupon doesn't exist in wc_sc_removed_auto_applied_coupons
* And sum of counts of both session variable will be considered before auto applying coupons. It will be made sure that the sum of counts in not exceeding option `wc_sc_max_auto_apply_coupons_limit`
* Reference: issues/234#note_27085
*/
public function auto_apply_coupons() {
$cart = ( is_object( WC() ) && isset( WC()->cart ) ) ? WC()->cart : null;
if ( is_object( $cart ) && is_callable( array( $cart, 'is_empty' ) ) && ! $cart->is_empty() && $this->is_allow_auto_apply_coupons() ) {
global $wpdb;
$user_role = '';
$email = '';
if ( ! is_admin() ) {
$current_user = wp_get_current_user();
if ( ! empty( $current_user->ID ) ) {
$max_user_roles_limit = apply_filters( 'wc_sc_max_user_roles_limit', 5 );
$user_roles = ( ! empty( $current_user->roles ) ) ? $current_user->roles : array();
if ( count( $user_roles ) > $max_user_roles_limit ) {
$user_roles = array_slice( $user_roles, 0, $max_user_roles_limit );
}
$email = get_user_meta( $current_user->ID, 'billing_email', true );
$email = ( ! empty( $email ) ) ? $email : $current_user->user_email;
}
}
$query = $wpdb->prepare(
"SELECT DISTINCT p.ID
FROM {$wpdb->posts} AS p
JOIN {$wpdb->postmeta} AS pm1
ON (p.ID = pm1.post_id
AND p.post_type = %s
AND p.post_status = %s
AND pm1.meta_key = %s
AND pm1.meta_value = %s)
JOIN {$wpdb->postmeta} AS pm2
ON (p.ID = pm2.post_id
AND pm2.meta_key IN ('wc_sc_user_role_ids', 'customer_email')
AND (pm2.meta_value = ''
OR pm2.meta_value = 'a:0:{}'",
'shop_coupon',
'publish',
'wc_sc_auto_apply_coupon',
'yes'
);
if ( ! empty( $user_roles ) ) {
foreach ( $user_roles as $user_role ) {
$query .= $wpdb->prepare(
' OR pm2.meta_value LIKE %s',
'%' . $wpdb->esc_like( $user_role ) . '%'
);
}
}
if ( ! empty( $email ) ) {
$query .= $wpdb->prepare(
' OR pm2.meta_value LIKE %s',
'%' . $wpdb->esc_like( $email ) . '%'
);
}
$query .= '))';
$auto_apply_coupon_ids = $wpdb->get_col( $query ); // phpcs:ignore
$auto_apply_coupon_ids = ( empty( $auto_apply_coupon_ids ) || ! is_array( $auto_apply_coupon_ids ) ) ? array() : $auto_apply_coupon_ids;
$auto_apply_coupon_ids = array_filter( array_map( 'absint', $auto_apply_coupon_ids ) );
if ( ! empty( $auto_apply_coupon_ids ) && is_array( $auto_apply_coupon_ids ) ) {
$valid_coupon_counter = 0;
$max_auto_apply_coupons_limit = apply_filters( 'wc_sc_max_auto_apply_coupons_limit', get_option( 'wc_sc_max_auto_apply_coupons_limit', 5 ), array( 'source' => $this ) );
$current_filter = current_filter();
do_action(
'wc_sc_before_auto_apply_coupons',
array(
'source' => $this,
'current_filter' => $current_filter,
)
);
foreach ( $auto_apply_coupon_ids as $apply_coupon_id ) {
// Process only five coupons.
if ( absint( $max_auto_apply_coupons_limit ) === $valid_coupon_counter ) {
break;
}
$coupon = new WC_Coupon( absint( $apply_coupon_id ) );
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
$coupon_code = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
// If coupon has payment method restriction and already store wc_sc_auto_applied_coupons.
$payment_method_ids = $this->get_post_meta( $coupon_id, 'wc_sc_payment_method_ids', true );
if ( ( is_array( $payment_method_ids ) && count( $payment_method_ids ) > 0 ) && $this->is_coupon_applied_by_auto_apply( $coupon_code ) ) {
$this->unset_auto_applied_coupon( $coupon_code );
}
// Check if it is a valid coupon object.
if ( $apply_coupon_id === $coupon_id && ! empty( $coupon_code ) && $this->is_coupon_valid_for_auto_apply( $coupon ) ) {
$cart_total = ( $this->is_wc_greater_than( '3.1.2' ) ) ? $cart->get_cart_contents_total() : $cart->cart_contents_total;
$is_auto_apply = apply_filters(
'wc_sc_is_auto_apply',
( $cart_total > 0 ),
array(
'source' => $this,
'cart_obj' => $cart,
'coupon_obj' => $coupon,
'cart_total' => $cart_total,
)
);
// Check if cart still requires a coupon discount and does not have coupon already applied.
if ( true === $is_auto_apply && ! $cart->has_discount( $coupon_code ) ) {
$cart->add_discount( $coupon_code );
$cart->calculate_shipping();
$cart->calculate_totals();
$this->set_auto_applied_coupon( $coupon_code );
}
$valid_coupon_counter++;
} // End if to check valid coupon.
}
}
}
}
/**
* Function to apply coupons for cart and checkout block.
*
* @param bool $pre_render Is protected.
* @param array $parsed_block The meta key.
* @param array $parent_block The meta type.
* @return bool
*/
public function auto_apply_coupons_to_cart_checkout_block( $pre_render = null, $parsed_block = array(), $parent_block = null ) {
if ( isset( $parsed_block['blockName'] ) && in_array( $parsed_block['blockName'], array( 'woocommerce/cart', 'woocommerce/checkout' ), true ) ) {
$this->auto_apply_coupons();
}
return $pre_render;
}
/**
* Function to Automatically Apply Coupons on Cart Update.
*
* @param string $cart_item_key contains the id of the cart item. This may be empty if the cart item does not exist any more.
* @param int $quantity contains the quantity of the item.
* @param WC_Cart $cart Cart class.
*/
public function auto_apply_coupons_on_cart_update( $cart_item_key, $quantity, $cart ) {
if ( WC()->is_rest_api_request() ) {
$this->auto_apply_coupons();
}
}
/**
* Automatically apply coupons during the WooCommerce checkout order review update process.
* This function checks for changes in the shipping method and updates the chosen shipping method in the session.
* Then, it automatically applies any eligible coupons.
*/
public function wc_checkout_update_order_review_auto_apply_coupons() {
check_ajax_referer( 'update-order-review', 'security' );
// Get the posted shipping methods from the form data, if available.
$posted_shipping_methods = isset( $_POST['shipping_method'] ) ? wc_clean( wp_unslash( $_POST['shipping_method'] ) ) : array(); // phpcs:ignore
if ( ! empty( $posted_shipping_methods ) ) {
// Retrieve the current chosen shipping methods from the session.
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
if ( is_array( $posted_shipping_methods ) ) {
// Update the chosen shipping methods with the posted values.
foreach ( $posted_shipping_methods as $i => $value ) {
if ( ! is_string( $value ) ) {
continue;
}
$chosen_shipping_methods[ $i ] = $value;
}
}
// Save the updated chosen shipping methods back to the session.
WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
}
// Automatically apply any eligible coupons.
$this->auto_apply_coupons();
}
/**
* Remove coupons that result in zero discount.
*
* This method loops through all applied coupons in the cart and checks if they are
* not present in the coupon discount totals. If a coupon is found to have a zero
* discount (i.e., it is not in the coupon discount totals), it is removed from the
* applied coupons list and the auto-applied coupon logic is handled.
*
* @param WC_Cart $cart The WooCommerce cart object.
*/
public function remove_coupon_if_zero( $cart ) {
// Get all applied coupons.
$applied_coupons = $cart->get_applied_coupons();
if ( ! empty( $applied_coupons ) ) {
foreach ( $applied_coupons as $coupon_code ) {
// Check if the coupon is not in the coupon discount totals (indicating a zero discount).
if ( ! array_key_exists( $coupon_code, $cart->get_coupon_discount_totals() ) ) {
// Remove the coupon from the applied coupons array.
$updated_coupons = array_diff( $applied_coupons, array( $coupon_code ) );
$cart->set_applied_coupons( $updated_coupons );
// Unset the auto-applied coupon from session.
$this->unset_auto_applied_coupon( $coupon_code );
}
}
}
}
/**
* Automatically apply coupons to the cart when the shipping method is changed.
* This method checks if the request is an AJAX request to update the shipping method,
* and if so, it calls the auto_apply_coupons method to apply any eligible coupons.
*/
public function auto_apply_coupons_to_cart_on_shipping_change() {
if ( is_ajax() ) {
// Check if the request is an AJAX request to update the shipping method.
check_ajax_referer( 'update-shipping-method', 'security' );
$this->auto_apply_coupons();
}
}
/**
* Handle auto apply related hooks
*/
public function handle_auto_apply_hooks() {
$is_allow_auto_apply = $this->sc_get_option( 'wc_sc_allow_auto_apply', 'yes' );
if ( 'yes' === $is_allow_auto_apply ) {
// Action to auto apply coupons.
add_action( 'woocommerce_cart_is_empty', array( $this, 'auto_apply_coupons' ) );
add_action( 'woocommerce_shortcode_before_product_cat_loop', array( $this, 'auto_apply_coupons' ) );
add_action( 'woocommerce_before_shop_loop', array( $this, 'auto_apply_coupons' ) );
add_action( 'woocommerce_before_single_product', array( $this, 'auto_apply_coupons' ) );
add_action( 'woocommerce_before_cart', array( $this, 'auto_apply_coupons' ) );
add_action( 'woocommerce_before_checkout_form', array( $this, 'auto_apply_coupons' ) );
add_action( 'woocommerce_account_content', array( $this, 'auto_apply_coupons' ) );
add_action( 'woocommerce_checkout_update_order_review', array( $this, 'wc_checkout_update_order_review_auto_apply_coupons' ) );
add_action( 'woocommerce_cart_emptied', array( $this, 'reset_auto_applied_coupons_session' ) );
add_action( 'woocommerce_removed_coupon', array( $this, 'blocks_removed_coupon' ), 20 );
add_action( 'woocommerce_removed_coupon', array( $this, 'wc_sc_removed_coupon' ), 99 );
add_filter( 'pre_render_block', array( $this, 'auto_apply_coupons_to_cart_checkout_block' ), 10, 3 );
add_action( 'woocommerce_cart_item_set_quantity', array( $this, 'auto_apply_coupons_on_cart_update' ), 10, 4 );
add_action( 'woocommerce_before_cart_totals', array( $this, 'auto_apply_coupons_to_cart_on_shipping_change' ) );
}
}
/**
* Recheck coupon removed from auto-apply
*
* @param string $code The coupon code.
*/
public function blocks_removed_coupon( $code = '' ) {
if ( empty( $code ) ) {
return;
}
if ( function_exists( 'WC' ) && isset( WC()->cart ) && is_a( WC()->cart, 'WC_Cart' ) ) {
$coupon = new WC_Coupon( $code );
$is_removable = $this->is_auto_apply_coupon_removable( $code );
$is_auto_applied = $this->is_coupon_applied_by_auto_apply( $code );
if ( true === $is_auto_applied && 'yes' !== $is_removable && $this->is_callable( WC()->cart, 'add_discount' ) ) {
WC()->cart->add_discount( $code );
}
}
}
}
}
WC_SC_Auto_Apply_Coupon::get_instance();

View File

@@ -0,0 +1,433 @@
<?php
/**
* WooCommerce Smart Coupon DB update.
*
* @author StoreApps
* @since 4.28.0
* @version 1.1.1
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Background_Upgrade' ) ) {
/**
* Class for WooCommerce Smart Coupons database update.
*/
class WC_SC_Background_Upgrade {
/**
* Number of row to fetch once a query run.
*
* (default value: 100)
*
* @var int
* @access protected
*/
protected $row_limit = 100;
/**
* Action name.
*
* @var string
* @access protected
*/
protected $action = '';
/**
* Variable to hold instance of WC_SC_Background_Upgrade
*
* @var $instance
*/
private static $instance = null;
/**
* Get single instance of WC_SC_Background_Upgrade
*
* @return WC_SC_Background_Upgrade Singleton object of WC_SC_Background_Upgrade
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Example_Background_Processing constructor.
*/
private function __construct() {
$this->action = 'wc_db_upgrade';
add_action( 'plugins_loaded', array( $this, 'init' ) );
add_action( 'init', array( $this, 'process_handler' ) );
add_action( 'init', array( $this, 'clear_all_process' ) );
add_action( 'action_scheduler_failed_action', array( $this, 'restart_failed_action' ) );
}
/**
* Init
*/
public function init() {
global $woocommerce_smart_coupon;
// Get list of db updates.
$updates = $this->get_updates();
if ( ! empty( $updates ) ) {
foreach ( $updates as $update ) {
// Break if version is empty.
if ( empty( $update['version'] ) ) {
break;
}
$version = $update['version'];
$update_status = $this->get_status( $version );
if ( version_compare( $woocommerce_smart_coupon->get_smart_coupons_version(), $version, '>=' ) && ( false === $update_status ) ) {
// Set db update status to pending.
$this->set_status( $version, 'pending' );
}
$handler = isset( $update['cron_handler'] ) ? $update['cron_handler'] : '';
$this->register_scheduler( $handler );
}
}
}
/**
* Process handler
*/
public function process_handler() {
if ( ! isset( $_GET['wc_sc_update'] ) || ! isset( $_GET['wc_sc_db_update_nonce'] ) ) {
return;
}
if ( ! wp_verify_nonce( wc_clean( wp_unslash( $_GET['wc_sc_db_update_nonce'] ) ), 'wc_sc_db_process' ) ) { // phpcs:ignore
return;
}
$this->handle_all( wc_clean( wp_unslash( $_GET['wc_sc_update'] ) ) ); // phpcs:ignore
}
/**
* Get list of db updates.
*/
public function get_updates() {
return array(
array(
'version' => '4.28.0', // Minimum plugin version to do the action.
'get_row_handler' => array( __CLASS__, 'get_applied_coupon_profile_options' ), // get data.
'cron_handler' => 'wcsc_move_applied_coupon_options_to_transient', // define cron handler which should be in this class.
),
);
}
/**
* Register action schedulers for db update.
*
* @param string $handler Handler name.
*/
public function register_scheduler( $handler = '' ) {
if ( ! empty( $handler ) && is_callable( array( $this, $handler ) ) ) {
add_action( $handler, array( $this, $handler ) );
}
}
/**
* Handle all updates.
*
* @param string $current_version Plugin version.
*/
protected function handle_all( $current_version = '0' ) {
if ( empty( $current_version ) ) {
return;
}
do_action( 'wc_sc_start_background_update', $current_version );
$updates = $this->get_updates();
if ( is_array( $updates ) && ! empty( $updates ) ) {
foreach ( $updates as $update ) {
// Compare version for db updates.
if ( ! empty( $update['version'] ) && version_compare( $current_version, $update['version'], '>=' ) ) {
$cron_handler = isset( $update['cron_handler'] ) ? $update['cron_handler'] : '';
if ( ! empty( $cron_handler ) && is_callable( array( $this, $cron_handler ) ) ) {
$row_handler = isset( $update['get_row_handler'] ) ? $update['get_row_handler'] : '';
$this->process( $update['version'], $cron_handler, $row_handler );
}
}
}
}
}
/**
* Handle the process.
*
* @param string $version Version number.
* @param string $cron_handler Cron handler action name.
* @param string $row_handler Fetch data handler name.
*/
private function process( $version = '', $cron_handler = '', $row_handler = '' ) {
$rows = ! empty( $row_handler ) && is_callable( $row_handler ) ? call_user_func( $row_handler ) : '';
if ( ! empty( $rows ) && is_array( $rows ) ) {
// Start the process if the status is pending.
if ( 'pending' === $this->get_status( $version ) ) {
if ( function_exists( 'as_enqueue_async_action' ) ) {
$this->set_status( $version, 'processing' );
as_enqueue_async_action( $cron_handler );
}
}
} else {
// Set status to `completed` if the data is empty.
$this->set_status( $version, 'completed' );
}
}
/**
* Clear all update process.
*/
public function clear_all_process() {
$updates = $this->get_updates();
foreach ( $updates as $update ) {
$version = isset( $update['version'] ) ? $update['version'] : '';
$row_handler = isset( $update['get_row_handler'] ) ? $update['get_row_handler'] : '';
$status = $this->get_status( $version );
if ( false === $status || 'done' === $status ) {
return;
}
$rows = ! empty( $row_handler ) && is_callable( $row_handler ) ? call_user_func( $row_handler ) : '';
if ( 'processing' === $status && empty( $rows ) ) {
do_action( 'wc_sc_background_update_completed', $version );
$this->set_status( $version, 'completed' );
}
}
}
/**
* Callback Method for move options to transient.
*
* @return void
*/
public function wcsc_move_applied_coupon_options_to_transient() {
$options = $this->get_applied_coupon_profile_options();
// Check if coupons are not empty.
if ( ! empty( $options ) && is_array( $options ) ) {
$start_time = time();
$loop = 1;
foreach ( $options as $option ) {
// disable auto apply.
$this->move_option_to_transient( $option );
if ( $this->loop_exceeded( $loop ) || $this->time_exceeded( $start_time ) || $this->memory_exceeded() ) {
// Update auto apply coupon id list.
if ( function_exists( 'as_enqueue_async_action' ) ) {
as_enqueue_async_action( __FUNCTION__ );
}
break;
}
$loop++;
}
}
}
/**
* Restart scheduler after one minute if it fails
*
* @param array $action_id id of failed action.
*/
public function restart_failed_action( $action_id = 0 ) {
if ( empty( $action_id ) || ! class_exists( 'ActionScheduler' ) || ! is_callable( array( 'ActionScheduler', 'store' ) ) || ! function_exists( 'as_enqueue_async_action' ) ) {
return;
}
$action = ActionScheduler::store()->fetch_action( $action_id );
$action_hook = $action->get_hook();
$updates = $this->get_updates();
if ( ! empty( $updates ) ) {
foreach ( $updates as $update ) {
if ( ! empty( $update['version'] ) && ! empty( $update['cron_handler'] ) ) {
if ( $action_hook === $update['cron_handler'] ) {
$this->set_status( $update['version'], 'processing' );
as_enqueue_async_action( $update['cron_handler'] );
}
}
}
}
}
/**
* Method to update the status of db upgrade.
*
* @param string $version wcsc db version.
* @param string $status status.
*
* @return bool.
*/
public function set_status( $version = '', $status = '' ) {
if ( ! empty( $version ) && ! empty( $status ) ) {
$db_status = get_option( 'sc_wc_db_update_status', array() );
$db_status[ $version ] = $status;
return update_option( 'sc_wc_db_update_status', $db_status, 'no' );
}
return false;
}
/**
* Method to get the status of db upgrade.
*
* @param string $version wcsc db version.
*
* @return bool.
*/
public function get_status( $version = '' ) {
if ( ! empty( $version ) ) {
$db_status = get_option( 'sc_wc_db_update_status', array() );
return ( ! empty( $db_status ) && isset( $db_status[ $version ] ) ) ? $db_status[ $version ] : false;
}
return false;
}
/**
* Loop exceeded
*
* Ensures the batch process never exceeds to handle the given limit of row.
*
* @param int $loop Number of loop done.
* @return bool
*/
public function loop_exceeded( $loop = 0 ) {
return $loop > apply_filters( $this->action . '_default_row_limit', $this->row_limit );
}
/**
* Memory exceeded
*
* Ensures the batch process never exceeds 90%
* of the maximum WordPress memory.
*
* @return bool
*/
protected function memory_exceeded() {
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
$current_memory = memory_get_usage( true );
if ( $current_memory >= $memory_limit ) {
return true;
}
return false;
}
/**
* Get memory limit.
*
* @return int
*/
protected function get_memory_limit() {
if ( function_exists( 'ini_get' ) ) {
$memory_limit = ini_get( 'memory_limit' );
} else {
// Sensible default.
$memory_limit = '128M';
}
if ( ! $memory_limit || -1 === intval( $memory_limit ) ) {
// Unlimited, set to 32GB.
$memory_limit = '32G';
}
return wp_convert_hr_to_bytes( $memory_limit );
}
/**
* Time exceeded.
*
* Ensures the batch never exceeds a sensible time limit.
* A timeout limit of 30s is common on shared hosting.
*
* @param string $start_time start timestamp.
* @return bool
*/
protected function time_exceeded( $start_time = '' ) {
$finish = $start_time + apply_filters( $this->action . '_default_time_limit', 20 ); // 20 seconds
$return = false;
if ( time() >= $finish ) {
$return = true;
}
return apply_filters( $this->action . '_time_exceeded', $return );
}
/**
* Get `applied_coupon_profile` options names and values
*
* @return array
*/
public function get_applied_coupon_profile_options() {
global $wpdb;
$option_name = 'sc_applied_coupon_profile_%';
$options = $wpdb->get_results( // @codingStandardsIgnoreLine
$wpdb->prepare(
"SELECT option_name, option_value
FROM $wpdb->options
WHERE option_name LIKE %s",
$option_name
),
ARRAY_A
);
return $options;
}
/**
* Method to transfer single options to transient.
*
* @param array $option Array of option name and value.
* @return void
*/
protected function move_option_to_transient( $option = array() ) {
if ( isset( $option['option_name'] ) && isset( $option['option_value'] ) ) {
// Add new transient with option name.
$move = set_transient(
$option['option_name'],
maybe_unserialize( $option['option_value'] ),
apply_filters( 'wc_sc_applied_coupon_by_url_expire_time', MONTH_IN_SECONDS )
);
if ( true === $move ) {
// Delete the option if option is successfully moved.
delete_option( $option['option_name'] );
}
}
}
} // End class
} // End class exists check
WC_SC_Background_Upgrade::get_instance();

View File

@@ -0,0 +1,865 @@
<?php
/**
* Handle coupon actions
*
* @author StoreApps
* @since 3.5.0
* @version 1.10.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupon_Actions' ) ) {
/**
* Class for handling processes of coupons
*/
class WC_SC_Coupon_Actions {
/**
* Variable to hold instance of WC_SC_Coupon_Actions
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_filter( 'woocommerce_add_cart_item', array( $this, 'modify_cart_item_data_in_add_to_cart' ), 15, 2 );
add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'modify_cart_item_in_session' ), 15, 3 );
add_filter( 'woocommerce_cart_item_quantity', array( $this, 'modify_cart_item_quantity' ), 5, 3 );
add_filter( 'woocommerce_cart_item_price', array( $this, 'modify_cart_item_price' ), 10, 3 );
add_filter( 'woocommerce_cart_item_subtotal', array( $this, 'modify_cart_item_price' ), 10, 3 );
add_filter( 'woocommerce_order_formatted_line_subtotal', array( $this, 'modify_cart_item_price' ), 10, 3 );
add_filter( 'woocommerce_coupon_get_items_to_validate', array( $this, 'remove_products_from_validation' ), 10, 2 );
add_action( 'woocommerce_applied_coupon', array( $this, 'coupon_action' ) );
add_action( 'woocommerce_removed_coupon', array( $this, 'remove_product_from_cart' ) );
add_action( 'woocommerce_check_cart_items', array( $this, 'review_cart_items' ) );
add_action( 'woocommerce_checkout_create_order_line_item', array( $this, 'add_product_source_in_order_item_meta' ), 10, 4 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'wc_sc_export_coupon_meta_data', array( $this, 'export_coupon_meta_data' ), 10, 2 );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_action_meta' ) );
add_filter( 'show_zero_amount_coupon', array( $this, 'show_coupon_with_actions' ), 10, 2 );
add_filter( 'wc_sc_is_auto_generate', array( $this, 'auto_generate_coupon_with_actions' ), 10, 2 );
add_filter( 'wc_sc_validate_coupon_amount', array( $this, 'validate_coupon_amount' ), 10, 2 );
add_filter( 'wc_sc_hold_applied_coupons', array( $this, 'maybe_run_coupon_actions' ), 10, 2 );
add_action( 'woocommerce_after_cart_item_quantity_update', array( $this, 'stop_cart_item_quantity_update' ), 99, 4 );
add_action( 'woocommerce_order_applied_coupon', array( $this, 'coupon_action' ), 10, 2 );
add_action( 'admin_init', array( $this, 'remove_product_from_order' ), 11 );
}
/**
* Get single instance of WC_SC_Coupon_Actions
*
* @return WC_SC_Coupon_Actions Singleton object of WC_SC_Coupon_Actions
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Get coupon actions
*
* @param string $coupon_code The coupon code.
* @return array Coupon actions
*/
public function get_coupon_actions( $coupon_code = '' ) {
if ( empty( $coupon_code ) ) {
return array();
}
$coupon_code = wc_format_coupon_code( $coupon_code );
$coupons = get_posts(
array(
'post_type' => 'shop_coupon',
'title' => $coupon_code,
'post_status' => 'publish',
'numberposts' => 1,
)
);
$coupon = current( $coupons );
$coupon_id = ( ! empty( $coupon->ID ) ) ? $coupon->ID : 0;
$coupon = new WC_Coupon( $coupon_id );
if ( ! is_wp_error( $coupon ) ) {
if ( $this->is_wc_gte_30() ) {
$actions = $coupon->get_meta( 'wc_sc_add_product_details' );
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$actions = get_post_meta( $coupon_id, 'wc_sc_add_product_details', true );
}
return apply_filters( 'wc_sc_coupon_actions', $actions, array( 'coupon_code' => $coupon_code ) );
}
return array();
}
/**
* Modify cart item data
*
* @param array $cart_item_data The cart item data.
* @param integer $product_id The product id.
* @param integer $variation_id The variation id.
* @param integer $quantity The quantity of product.
* @return array $cart_item_data
*/
public function modify_cart_item_data( $cart_item_data = array(), $product_id = 0, $variation_id = 0, $quantity = 0 ) {
if ( empty( $cart_item_data ) || empty( $product_id ) || empty( $quantity ) ) {
return $cart_item_data;
}
if ( ! empty( $cart_item_data['wc_sc_product_source'] ) ) {
$coupon_code = $cart_item_data['wc_sc_product_source'];
$coupon_actions = $this->get_coupon_actions( $coupon_code );
if ( ! empty( $coupon_actions ) && ! is_scalar( $coupon_actions ) ) {
foreach ( $coupon_actions as $product_data ) {
if ( ! empty( $product_data['product_id'] ) && in_array( absint( $product_data['product_id'] ), array_map( 'absint', array( $product_id, $variation_id ) ), true ) ) {
$discount_amount = ( '' !== $product_data['discount_amount'] ) ? $product_data['discount_amount'] : '';
if ( '' !== $discount_amount ) {
if ( ! empty( $variation_id ) ) {
$product = wc_get_product( $variation_id );
} else {
$product = wc_get_product( $product_id );
}
$product_price = $product->get_price();
$regular_price = $product->get_regular_price();
$discount_type = ( ! empty( $product_data['discount_type'] ) ) ? $product_data['discount_type'] : 'percent';
switch ( $discount_type ) {
case 'flat':
$discount = $this->convert_price( $discount_amount );
break;
case 'percent':
$discount = ( $product_price * $discount_amount ) / 100;
break;
}
$discount = wc_cart_round_discount( min( $product_price, $discount ), 2 );
$discounted_price = $product_price - $discount;
$cart_item_data['data']->set_price( $discounted_price );
$cart_item_data['data']->set_regular_price( $regular_price );
$cart_item_data['data']->set_sale_price( $discounted_price );
}
break;
}
}
}
}
return $cart_item_data;
}
/**
* Modify cart item in WC_Cart::add_to_cart()
*
* @param array $cart_item_data The cart item data as passed by filter 'woocommerce_add_cart_item'.
* @param string $cart_item_key The cart item key.
* @return array $cart_item_data
*/
public function modify_cart_item_data_in_add_to_cart( $cart_item_data = array(), $cart_item_key = '' ) {
if ( ! empty( $cart_item_data['wc_sc_product_source'] ) ) {
$cart_item_data = $this->modify_cart_item_data( $cart_item_data, $cart_item_data['product_id'], $cart_item_data['variation_id'], $cart_item_data['quantity'] );
}
return $cart_item_data;
}
/**
* Modify cart item in session
*
* @param array $session_data The session data.
* @param array $values The cart item.
* @param string $key The cart item key.
* @return array $session_data
*/
public function modify_cart_item_in_session( $session_data = array(), $values = array(), $key = '' ) {
if ( ! empty( $values['wc_sc_product_source'] ) ) {
$session_data['wc_sc_product_source'] = $values['wc_sc_product_source'];
$qty = ( ! empty( $session_data['quantity'] ) ) ? absint( $session_data['quantity'] ) : ( ( ! empty( $values['quantity'] ) ) ? absint( $values['quantity'] ) : 1 );
$session_data = $this->modify_cart_item_data( $session_data, $session_data['product_id'], $session_data['variation_id'], $qty );
}
return $session_data;
}
/**
* Modify cart item quantity
*
* @param string $product_quantity The product quantity.
* @param string $cart_item_key The cart item key.
* @param array $cart_item The cart item.
* @return string $product_quantity
*/
public function modify_cart_item_quantity( $product_quantity = '', $cart_item_key = '', $cart_item = array() ) {
if ( ! empty( $cart_item['wc_sc_product_source'] ) ) {
$product_quantity = sprintf( '%s <input type="hidden" name="cart[%s][qty]" value="%s" />', $cart_item['quantity'], $cart_item_key, $cart_item['quantity'] );
}
return $product_quantity;
}
/**
* Modify cart item price
*
* @param string $product_price The product price.
* @param array $cart_item The cart item.
* @param string $cart_item_key The cart item key.
* @return string $product_price
*/
public function modify_cart_item_price( $product_price = '', $cart_item = array(), $cart_item_key = '' ) {
if ( ( is_array( $cart_item ) && isset( $cart_item['wc_sc_product_source'] ) ) || ( is_object( $cart_item ) && is_callable( array( $cart_item, 'get_meta' ) ) && $cart_item->get_meta( '_wc_sc_product_source' ) ) ) {
if ( wc_price( 0 ) === $product_price ) {
$product_price = apply_filters(
'wc_sc_price_zero_text',
$product_price,
array(
'cart_item' => $cart_item,
'cart_item_key' => $cart_item_key,
)
);
}
}
return $product_price;
}
/**
* Remove products added by the coupon from validation
*
* Since the filter 'woocommerce_coupon_get_items_to_validate' is added in WooCommerce 3.4.0, this function will work only in WC 3.4.0+
* Otherwise, the products added by coupon might get double discounts applied
*
* @param array $items The cart/order items.
* @param WC_Discounts $discounts The discounts object.
* @return mixed $items
*/
public function remove_products_from_validation( $items = array(), $discounts = null ) {
if ( ! empty( $items ) && ! is_scalar( $items ) ) {
foreach ( $items as $index => $item ) {
$coupon_code = '';
if ( is_array( $item->object ) && isset( $item->object['wc_sc_product_source'] ) ) {
$coupon_code = $item->object['wc_sc_product_source'];
} elseif ( is_a( $item->object, 'WC_Order_Item' ) && is_callable( array( $item->object, 'get_meta' ) ) && $item->object->get_meta( '_wc_sc_product_source' ) ) {
$coupon_code = $item->object->get_meta( '_wc_sc_product_source' );
}
if ( ! empty( $coupon_code ) ) {
$item_product_id = ( is_a( $item->product, 'WC_Product' ) && is_callable( array( $item->product, 'get_id' ) ) ) ? $item->product->get_id() : 0;
$coupon_actions = $this->get_coupon_actions( $coupon_code );
if ( ! empty( $coupon_actions ) && ! is_scalar( $coupon_actions ) ) {
foreach ( $coupon_actions as $product_data ) {
if ( ! empty( $product_data['product_id'] ) && absint( $product_data['product_id'] ) === absint( $item_product_id ) ) {
$discount_amount = ( '' !== $product_data['discount_amount'] ) ? $product_data['discount_amount'] : '';
if ( '' !== $discount_amount ) {
unset( $items[ $index ] );
}
}
}
}
}
}
}
return $items;
}
/**
* Apply coupons actions
*
* @param string $coupon_code The coupon code.
* @param WC_Order $order WooCommerce order instance.
*/
public function coupon_action( $coupon_code = '', $order = null ) {
if ( empty( $coupon_code ) ) {
return;
}
if ( $coupon_code instanceof WC_Coupon && is_callable( array( $coupon_code, 'get_code' ) ) ) {
$coupon_code = $coupon_code->get_code();
}
$coupon_actions = $this->get_coupon_actions( $coupon_code );
if ( ! empty( $coupon_actions ) && ! is_scalar( $coupon_actions ) ) {
$product_names = array();
foreach ( $coupon_actions as $coupon_action ) {
if ( empty( $coupon_action['product_id'] ) ) {
continue;
}
$id = absint( $coupon_action['product_id'] );
$product = wc_get_product( $id );
$product_data = $this->get_product_data( $product );
$product_id = ( ! empty( $product_data['product_id'] ) ) ? absint( $product_data['product_id'] ) : 0;
$variation_id = ( ! empty( $product_data['variation_id'] ) ) ? absint( $product_data['variation_id'] ) : 0;
$variation = array();
if ( ! empty( $variation_id ) ) {
$variation = $product->get_variation_attributes();
}
$quantity = absint( $coupon_action['quantity'] );
$cart_item_data = array(
'wc_sc_product_source' => $coupon_code,
);
if ( $order instanceof WC_Abstract_Order ) {
$product_exists = false;
$order_items = $order->get_items();
foreach ( $order_items as $order_item ) {
if ( absint( $order_item->get_product_id() ) === $product_id ) {
$product_exists = true; // Exit if the product is already in the order.
break;
}
}
if ( ! $product_exists ) {
// Add a line item to the order.
$item = new WC_Order_Item_Product();
$discount_amount = ( '' !== $product_data['discount_amount'] ) ? $coupon_action['discount_amount'] : '';
$discount_type = ( ! empty( $coupon_action['discount_type'] ) ) ? $coupon_action['discount_type'] : 'percent';
switch ( $discount_type ) {
case 'flat':
$discount = $this->convert_price( $discount_amount );
break;
case 'percent':
$discount = ( $product->get_price() * $discount_amount ) / 100;
break;
}
// Calculated the discounted amount.
$discounted_price = ( $product->get_price() - $discount ) * $quantity;
$item->set_props(
array(
'name' => $product->get_name(),
'product_id' => $product_id, // ID of the product to add.
'quantity' => $quantity, // Quantity of the product.
'variation_id' => $variation_id, // ID of the product variation (if applicable).
)
);
$item->set_subtotal( $discounted_price );
$item->add_meta_data( '_wc_sc_product_source', $coupon_code );
$item->set_order_id( $order->get_id() );
// Add the item to the order.
$order->add_item( $item );
}
} else {
$cart_item_key = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $cart_item_data );
if ( ! empty( $cart_item_key ) ) {
if ( $this->is_wc_gte_30() ) {
$product_names[] = ( is_object( $product ) && is_callable( array( $product, 'get_name' ) ) ) ? $product->get_name() : '';
} else {
$product_names[] = ( is_object( $product ) && is_callable( array( $product, 'get_title' ) ) ) ? $product->get_title() : '';
}
}
}
}
if ( ! ( $order instanceof WC_Abstract_Order ) && ! empty( $product_names ) ) {
/* translators: 1. Product title */
wc_add_notice( sprintf( __( '%s has been added to your cart!', 'woocommerce-smart-coupons' ), implode( ', ', $product_names ) ) );
}
}
}
/**
* Remove products from cart if the coupon, which added the product, is removed
*
* @param string $coupon_code The coupon code.
*/
public function remove_product_from_cart( $coupon_code = '' ) {
if ( is_admin() ) {
return;
}
if ( ! empty( $coupon_code ) ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if ( isset( $cart_item['wc_sc_product_source'] ) && $cart_item['wc_sc_product_source'] === $coupon_code ) {
// Action 'woocommerce_before_calculate_totals' is hooked by WooCommerce Subscription while removing coupons in local WooCommerce Cart variable in which we don't need to remove added cart item.
if ( ! doing_action( 'woocommerce_before_calculate_totals' ) ) {
WC()->cart->set_quantity( $cart_item_key, 0 );
}
}
}
}
}
/**
* Remove products added by coupon actions when the coupon is removed from the order.
*/
public function remove_product_from_order() {
$action = ( ! empty( $_POST['action'] ) ) ? wc_clean( wp_unslash( $_POST['action'] ) ) : ''; // phpcs:ignore
$coupon_code = ( ! empty( $_POST['coupon'] ) ) ? wc_clean( wp_unslash( $_POST['coupon'] ) ) : ''; // phpcs:ignore
$order_id = ( ! empty( $_POST['order_id'] ) ) ? wc_clean( wp_unslash( $_POST['order_id'] ) ) : 0; // phpcs:ignore
if ( 'woocommerce_remove_order_coupon' !== $action || empty( $order_id ) || empty( $coupon_code ) ) {
return;
}
$order = wc_get_order( $order_id );
if ( ! $order instanceof WC_Order ) {
return;
}
foreach ( $order->get_items() as $item_id => $item ) {
if ( $item->get_meta( '_wc_sc_product_source', true ) === $coupon_code ) {
$order->remove_item( $item_id );
}
}
$order->calculate_totals(); // Recalculate totals.
$order->save(); // Save the order.
}
/**
* Review cart items
*/
public function review_cart_items() {
$cart = ( is_object( WC() ) && isset( WC()->cart ) ) ? WC()->cart : null;
$applied_coupons = isset( $cart->applied_coupons ) ? (array) $cart->applied_coupons : array();
$products = array();
if ( $cart instanceof WC_Cart && is_callable( array( $cart, 'get_cart' ) ) ) {
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
if ( ! empty( $cart_item['wc_sc_product_source'] ) && ! in_array( $cart_item['wc_sc_product_source'], $applied_coupons, true ) ) {
$cart->set_quantity( $cart_item_key, 0 );
$coupon_code = $cart_item['wc_sc_product_source'];
if ( empty( $products[ $coupon_code ] ) || ! is_array( $products[ $coupon_code ] ) ) {
$products[ $coupon_code ] = array();
}
$products[ $coupon_code ][] = ( is_object( $cart_item['data'] ) && is_callable( array( $cart_item['data'], 'get_name' ) ) ) ? $cart_item['data']->get_name() : '';
$products[ $coupon_code ] = array_filter( $products[ $coupon_code ] );
}
}
}
if ( ! empty( $products ) && ! is_scalar( $products ) ) {
foreach ( $products as $coupon_code => $product_names ) {
/* translators: 1. Product/s 2. Product names 3. is/are 4. Coupons code */
wc_add_notice( sprintf( __( '%1$s %2$s %3$s removed because coupon %4$s is removed.', 'woocommerce-smart-coupons' ), _n( 'Product', 'Products', count( $products[ $coupon_code ] ), 'woocommerce-smart-coupons' ), '<strong>' . implode( ', ', $products[ $coupon_code ] ) . '</strong>', _n( 'is', 'are', count( $products[ $coupon_code ] ), 'woocommerce-smart-coupons' ), '<code>' . $coupon_code . '</code>' ), 'error' );
}
}
}
/**
* Add product source in order item meta
*
* @param mixed $item The item.
* @param string $cart_item_key The cart item key.
* @param array $values The cart item.
* @param WC_Order $order The order.
*/
public function add_product_source_in_order_item_meta( $item = null, $cart_item_key = '', $values = array(), $order = null ) {
if ( isset( $values['wc_sc_product_source'] ) ) {
$item->add_meta_data( '_wc_sc_product_source', $values['wc_sc_product_source'], true );
}
}
/**
* Get product data
*
* @param mixed $product The product object.
* @return array
*/
public function get_product_data( $product = null ) {
if ( empty( $product ) ) {
return array();
}
if ( $this->is_wc_gte_30() ) {
$product_id = ( is_object( $product ) && is_callable( array( $product, 'get_id' ) ) ) ? $product->get_id() : 0;
} else {
$product_id = ( ! empty( $product->id ) ) ? $product->id : 0;
}
$product_type = ( is_object( $product ) && is_callable( array( $product, 'get_type' ) ) ) ? $product->get_type() : '';
if ( 'variation' === $product_type ) {
$variation_id = $product_id;
if ( $this->is_wc_gte_30() ) {
$parent_id = ( is_object( $product ) && is_callable( array( $product, 'get_parent_id' ) ) ) ? $product->get_parent_id() : 0;
$variation_data = wc_get_product_variation_attributes( $variation_id );
} else {
$parent_id = ( is_object( $product ) && is_callable( array( $product, 'get_parent' ) ) ) ? $product->get_parent() : 0;
$variation_data = ( ! empty( $product->variation_data ) ) ? $product->variation_data : array();
}
$product_id = $parent_id;
} else {
$variation_id = 0;
$variation_data = array();
}
$product_data = array(
'product_id' => $product_id,
'variation_id' => $variation_id,
'variation_data' => $variation_data,
);
return apply_filters( 'wc_sc_product_data', $product_data, array( 'product_obj' => $product ) );
}
/**
* Add action's meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$action_headers = array(
'wc_sc_add_product_details' => __( 'Add product details', 'woocommerce-smart-coupons' ),
);
return array_merge( $headers, $action_headers );
}
/**
* Function to handle coupon meta data during export of existing coupons
*
* @param mixed $meta_value The meta value.
* @param array $args Additional arguments.
* @return string Processed meta value
*/
public function export_coupon_meta_data( $meta_value = '', $args = array() ) {
$index = ( ! empty( $args['index'] ) ) ? $args['index'] : -1;
$meta_keys = ( ! empty( $args['meta_keys'] ) ) ? $args['meta_keys'] : array();
$meta_values = ( ! empty( $args['meta_values'] ) ) ? $args['meta_values'] : array();
if ( $index >= 0 && ! empty( $meta_keys[ $index ] ) && 'wc_sc_add_product_details' === $meta_keys[ $index ] ) {
if ( ! empty( $meta_value ) && is_array( $meta_value ) ) {
$product_details = array();
foreach ( $meta_value as $value ) {
$product_details[] = implode( ',', $value );
}
$meta_value = implode( '|', $product_details );
}
}
return $meta_value;
}
/**
* Post meta defaults for action's meta
*
* @param array $defaults Existing postmeta defaults.
* @return array
*/
public function postmeta_defaults( $defaults = array() ) {
$actions_defaults = array(
'wc_sc_add_product_details' => '',
);
return array_merge( $defaults, $actions_defaults );
}
/**
* Add action's meta with value in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array Modified data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
if ( isset( $post['wc_sc_add_product_ids'] ) ) {
if ( $this->is_wc_gte_30() ) {
$product_ids = wc_clean( wp_unslash( $post['wc_sc_add_product_ids'] ) ); // phpcs:ignore
} else {
$product_ids = array_filter( array_map( 'trim', explode( ',', sanitize_text_field( wp_unslash( $post['wc_sc_add_product_ids'] ) ) ) ) ); // phpcs:ignore
}
$add_product_details = array();
if ( ! empty( $product_ids ) && ! is_scalar( $product_ids ) ) {
$quantity = ( isset( $post['wc_sc_add_product_qty'] ) ) ? wc_clean( wp_unslash( $post['wc_sc_add_product_qty'] ) ) : 1;
$discount_amount = ( isset( $post['wc_sc_product_discount_amount'] ) ) ? wc_clean( wp_unslash( $post['wc_sc_product_discount_amount'] ) ) : '';
$discount_type = ( isset( $post['wc_sc_product_discount_type'] ) ) ? wc_clean( wp_unslash( $post['wc_sc_product_discount_type'] ) ) : '';
foreach ( $product_ids as $id ) {
$product_data = array();
$product_data['product_id'] = $id;
$product_data['quantity'] = $quantity;
$product_data['discount_amount'] = $discount_amount;
$product_data['discount_type'] = $discount_type;
$add_product_details[] = implode( ',', $product_data );
}
}
$data['wc_sc_add_product_details'] = implode( '|', $add_product_details );
}
return $data;
}
/**
* Make meta data of SC actions, protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected, $meta_key, $meta_type ) {
$sc_meta = array(
'wc_sc_add_product_details',
);
if ( in_array( $meta_key, $sc_meta, true ) ) {
return true;
}
return $protected;
}
/**
* Function to copy coupon action meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_action_meta( $args = array() ) {
$new_coupon_id = ( ! empty( $args['new_coupon_id'] ) ) ? absint( $args['new_coupon_id'] ) : 0;
$coupon = ( ! empty( $args['ref_coupon'] ) ) ? $args['ref_coupon'] : false;
if ( empty( $new_coupon_id ) || empty( $coupon ) ) {
return;
}
$add_product_details = array();
if ( $this->is_wc_gte_30() ) {
$add_product_details = $coupon->get_meta( 'wc_sc_add_product_details' );
} else {
$old_coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$add_product_details = get_post_meta( $old_coupon_id, 'wc_sc_add_product_details', true );
}
$this->update_post_meta( $new_coupon_id, 'wc_sc_add_product_details', $add_product_details );
}
/**
* Function to validate whether to show the coupon or not
*
* @param boolean $is_show Show or not.
* @param array $args Additional arguments.
* @return boolean
*/
public function show_coupon_with_actions( $is_show = false, $args = array() ) {
$coupon = ( ! empty( $args['coupon'] ) ) ? $args['coupon'] : null;
if ( empty( $coupon ) ) {
return $is_show;
}
if ( $this->is_wc_gte_30() ) {
$coupon_code = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
} else {
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
$coupon_actions = $this->get_coupon_actions( $coupon_code );
if ( ! empty( $coupon_actions ) ) {
return true;
}
return $is_show;
}
/**
* Allow auto-generate of coupon with coupon action
*
* @param boolean $is_auto_generate Whether to auto-generate or not.
* @param array $args Additional parameters.
* @return boolean $is_auto_generate
*/
public function auto_generate_coupon_with_actions( $is_auto_generate = false, $args = array() ) {
$coupon = ( ! empty( $args['coupon_obj'] ) && $args['coupon_obj'] instanceof WC_Coupon ) ? $args['coupon_obj'] : false;
$coupon_id = ( ! empty( $args['coupon_id'] ) ) ? $args['coupon_id'] : false;
if ( ! empty( $coupon ) && ! empty( $coupon_id ) ) {
if ( $this->is_wc_gte_30() ) {
$coupon_code = $coupon->get_code();
} else {
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
if ( ! empty( $coupon_code ) ) {
$actions = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_sc_add_product_details' ) : get_post_meta( $coupon_id, 'wc_sc_add_product_details', true );
$coupon_actions = apply_filters(
'wc_sc_coupon_actions',
$actions,
array(
'coupon_code' => $coupon_code,
'source' => $this,
)
);
if ( ! empty( $coupon_actions ) ) {
return true;
}
}
}
return $is_auto_generate;
}
/**
* Validate coupon having actions but without an amount
*
* @param boolean $is_valid_coupon_amount Whether the amount is validate or not.
* @param array $args Additional parameters.
* @return boolean
*/
public function validate_coupon_amount( $is_valid_coupon_amount = true, $args = array() ) {
if ( ! $is_valid_coupon_amount ) {
$coupon_amount = ( ! empty( $args['coupon_amount'] ) ) ? $args['coupon_amount'] : 0;
$discount_type = ( ! empty( $args['discount_type'] ) ) ? $args['discount_type'] : '';
$coupon_code = ( ! empty( $args['coupon_code'] ) ) ? $args['coupon_code'] : '';
$coupon_actions = ( ! empty( $coupon_code ) ) ? $this->get_coupon_actions( $coupon_code ) : array();
if ( 'smart_coupon' === $discount_type && $coupon_amount <= 0 && ! empty( $coupon_actions ) ) {
return true;
}
}
return $is_valid_coupon_amount;
}
/**
* Handle coupon actions when the cart is empty
*
* @param boolean $is_hold Whether to hold the coupon in cookie.
* @param array $args Additional arguments.
* @return boolean
*/
public function maybe_run_coupon_actions( $is_hold = true, $args = array() ) {
$cart = ( is_object( WC() ) && isset( WC()->cart ) ) ? WC()->cart : null;
if ( empty( $cart ) || WC()->cart->is_empty() ) {
$coupons_data = ( ! empty( $args['coupons_data'] ) ) ? $args['coupons_data'] : array();
if ( ! empty( $coupons_data ) && ! is_scalar( $coupons_data ) ) {
foreach ( $coupons_data as $coupon_data ) {
$coupon_code = ( ! empty( $coupon_data['coupon-code'] ) ) ? $coupon_data['coupon-code'] : '';
if ( ! empty( $coupon_code ) ) {
$coupon = new WC_Coupon( $coupon_code );
$coupon_actions = $this->get_coupon_actions( $coupon_code );
$coupon_products = ( ! empty( $coupon_actions ) ) ? wp_list_pluck( $coupon_actions, 'product_id' ) : array();
if ( ! empty( $coupon_products ) ) {
if ( $this->is_valid( $coupon ) && ! WC()->cart->has_discount( $coupon_code ) ) {
WC()->cart->add_discount( trim( $coupon_code ) );
$is_hold = false;
}
}
}
}
}
}
return $is_hold;
}
/**
* Stop product update option for action tab products.
*
* @param string $cart_item_key contains the id of the cart item.
* @param int $quantity Current quantity of the item.
* @param int $old_quantity Old quantity of the item.
* @param WC_Cart $cart Cart object.
* @return void
*/
public function stop_cart_item_quantity_update( $cart_item_key = '', $quantity = 1, $old_quantity = 1, $cart = object ) {
if ( empty( $cart_item_key ) || ! is_object( $cart ) || ! is_a( $cart, 'WC_Cart' ) ) {
return;
}
$cart_data = is_callable( array( $cart, 'get_cart' ) ) ? $cart->get_cart() : array();
$cart_item = ( ! empty( $cart_data[ $cart_item_key ] ) ) ? $cart_data[ $cart_item_key ] : array();
if ( empty( $cart_item ) ) {
return;
}
$applied_coupons = is_callable( array( $cart, 'get_applied_coupons' ) ) ? $cart->get_applied_coupons() : array();
if ( ! empty( $cart_item['wc_sc_product_source'] ) && in_array( $cart_item['wc_sc_product_source'], $applied_coupons, true ) ) {
$cart->cart_contents[ $cart_item_key ]['quantity'] = $old_quantity;
}
}
}
}
WC_SC_Coupon_Actions::get_instance();

View File

@@ -0,0 +1,253 @@
<?php
/**
* Smart Coupons category fields in coupons
*
* @author StoreApps
* @since 4.8.0
* @version 1.4.0
*
* @package woocommerce-smart-coupons/includes/
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WC_SC_Coupon_Categories' ) ) {
/**
* Class for handling Smart Coupons' field in coupons
*/
class WC_SC_Coupon_Categories {
/**
* Variable to hold instance of WC_SC_Coupon_Categories
*
* @var $instance
*/
private static $instance = null;
/**
* Get single instance of WC_SC_Coupon_Categories
*
* @return WC_SC_Coupon_Categories Singleton object of WC_SC_Coupon_Categories
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
add_action( 'init', array( $this, 'wc_sc_coupons_add_category' ) );
add_filter( 'parent_file', array( $this, 'wc_sc_make_menu_active' ) );
add_action( 'admin_footer', array( $this, 'add_footer_script' ) );
add_filter( 'manage_edit-sc_coupon_category_columns', array( $this, 'wc_sc_coupon_category_id_column' ) );
add_filter( 'manage_sc_coupon_category_custom_column', array( $this, 'wc_sc_coupon_category_id_column_content' ), 10, 3 );
add_filter( 'manage_edit-sc_coupon_category_sortable_columns', array( $this, 'wc_sc_define_sortable_id_columns' ) );
add_filter( 'manage_shop_coupon_posts_columns', array( $this, 'define_columns' ), 11 );
add_action( 'manage_shop_coupon_posts_custom_column', array( $this, 'render_columns' ), 10, 2 );
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Register custom taxonomy called sc_coupon_category.
*/
public function wc_sc_coupons_add_category() {
$labels = array(
'name' => __( 'Coupon categories', 'woocommerce-smart-coupons' ),
'singular_name' => __( 'Category', 'woocommerce-smart-coupons' ),
'menu_name' => _x( 'Categories', 'Admin menu name', 'woocommerce-smart-coupons' ),
'search_items' => __( 'Search coupon categories', 'woocommerce-smart-coupons' ),
'all_items' => __( 'All coupon categories', 'woocommerce-smart-coupons' ),
'parent_item' => __( 'Parent coupon category', 'woocommerce-smart-coupons' ),
'parent_item_colon' => __( 'Parent coupon category:', 'woocommerce-smart-coupons' ),
'edit_item' => __( 'Edit coupon category', 'woocommerce-smart-coupons' ),
'update_item' => __( 'Update coupon category', 'woocommerce-smart-coupons' ),
'add_new_item' => __( 'Add new coupon category', 'woocommerce-smart-coupons' ),
'new_item_name' => __( 'New coupon category name', 'woocommerce-smart-coupons' ),
'not_found' => __( 'No coupon categories found', 'woocommerce-smart-coupons' ),
);
register_taxonomy(
'sc_coupon_category', // Taxonomy name.
array( 'shop_coupon' ), // object for which the taxonomy is created.
array(
'labels' => $labels,
'description' => __( 'Manage coupon categories', 'woocommerce-smart-coupons' ),
'public' => true,
'hierarchical' => true,
'show_ui' => true,
'show_in_menu' => false,
'show_in_rest' => true,
'show_admin_column' => true,
'rewrite' => array( 'slug' => 'sc_coupon_category' ),
'query_var' => true,
)
);
register_taxonomy_for_object_type( 'sc_coupon_category', 'shop_coupon' );
}
/**
* Function to render coupon category column on coupons dashboard.
*
* @param int $post_id The coupon ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function render_coupon_category_column( $post_id = 0, $coupon = null ) {
$terms = get_the_terms( $post_id, 'sc_coupon_category' );
if ( ! empty( $terms ) ) {
foreach ( $terms as $term ) {
$content[] = '<a href="' . esc_url( admin_url( 'edit.php?sc_coupon_category=' . $term->slug . '&post_type=shop_coupon' ) ) . '">' . esc_html( $term->name ) . '</a>';
}
echo join( ', ', $content ); // phpcs:ignore
} else {
echo '<span class="na">&ndash;</span>';
}
}
/**
* Function to set woocommerce menu active
*
* @param string $parent_file file reference for menu.
*/
public function wc_sc_make_menu_active( $parent_file ) {
global $current_screen;
$taxonomy = $current_screen->taxonomy;
if ( 'sc_coupon_category' === $taxonomy ) {
if ( $this->is_wc_gte_44() ) {
$parent_file = 'woocommerce-marketing';
} else {
$parent_file = 'woocommerce';
}
}
return $parent_file;
}
/**
* Function to add custom script in admin footer.
*/
public function add_footer_script() {
global $pagenow, $post;
$get_post_type = ( ! empty( $post->ID ) ) ? $this->get_post_type( $post->ID ) : ( ( ! empty( $_GET['post_type'] ) ) ? wc_clean( wp_unslash( $_GET['post_type'] ) ) : '' ); // phpcs:ignore
if ( 'shop_coupon' === $get_post_type ) {
if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) {
$manage_category_string = __( 'Manage coupon categories', 'woocommerce-smart-coupons' );
?>
<script type="text/javascript">
jQuery(function() {
jQuery('#sc_coupon_category-tabs').before('<div class="sc-manage-category"><a target="_blank" href="<?php echo esc_url( admin_url( 'edit-tags.php?taxonomy=sc_coupon_category&post_type=shop_coupon' ) ); ?> "><?php echo esc_html( $manage_category_string ); ?></a></div>');
});
</script>
<?php
}
}
}
/**
* Function for add id column in coupon category taxonomy page.
*
* @param array $columns - Existing headers.
* @return array
*/
public function wc_sc_coupon_category_id_column( $columns = array() ) {
if ( ! empty( $columns ) ) {
return array_slice( $columns, 0, 1, true ) + array( 'id' => 'ID' ) + array_slice( $columns, 1, count( $columns ) - 1, true );
}
return $columns;
}
/**
* Function for add content to ID column of coupon category taxonomy page.
*
* @param string $content - column content.
* @param string $column_name - column_name.
* @param string $term_id - id.
* @return string
*/
public function wc_sc_coupon_category_id_column_content( $content = '', $column_name = '', $term_id = 0 ) {
return $term_id;
}
/**
* Function for change ID column to sortable.
*
* @param array $columns - Existing columns.
* @return array
*/
public function wc_sc_define_sortable_id_columns( $columns = array() ) {
$columns['id'] = 'id';
return $columns;
}
/**
* Define which columns to show on this screen.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_columns( $columns = array() ) {
if ( ! is_array( $columns ) || empty( $columns ) ) {
$columns = array();
}
$columns['wc_sc_coupon_category'] = __( 'Coupon categories', 'woocommerce-smart-coupons' );
return $columns;
}
/**
* Render individual columns.
*
* @param string $column Column ID to render.
* @param int $post_id Post ID being shown.
*/
public function render_columns( $column = '', $post_id = 0 ) {
if ( empty( $post_id ) || empty( $column ) || 'wc_sc_coupon_category' !== $column ) {
return;
}
$coupon = new WC_Coupon( $post_id );
$this->render_coupon_category_column( $post_id, $coupon );
}
}
}
WC_SC_Coupon_Categories::get_instance();

View File

@@ -0,0 +1,200 @@
<?php
/**
* Handle coupon columns
*
* @author StoreApps
* @since 4.5.2
* @version 1.3.1
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupon_Columns' ) ) {
/**
* Class for handling coupon columns
*/
class WC_SC_Coupon_Columns {
/**
* Variable to hold instance of WC_SC_Coupon_Columns
*
* @var $instance
*/
private static $instance = null;
/**
* Post type.
*
* @var string
*/
protected $list_table_type = 'shop_coupon';
/**
* Object being shown on the row.
*
* @var object|null
*/
protected $object = null;
/**
* Constructor
*/
private function __construct() {
add_filter( 'manage_' . $this->list_table_type . '_posts_columns', array( $this, 'define_columns' ), 11 );
add_action( 'manage_' . $this->list_table_type . '_posts_custom_column', array( $this, 'render_columns' ), 10, 2 );
}
/**
* Get single instance of WC_SC_Coupon_Columns
*
* @return WC_SC_Coupon_Columns Singleton object of WC_SC_Coupon_Columns
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Pre-fetch any data for the row each column has access to it.
*
* @param int $post_id Post ID being shown.
*/
protected function prepare_row_data( $post_id = 0 ) {
if ( empty( $post_id ) ) {
return;
}
$coupon_id = 0;
if ( ! empty( $this->object ) ) {
$coupon = $this->object;
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
}
}
if ( empty( $this->object ) || $coupon_id !== $post_id ) {
$this->object = new WC_Coupon( $post_id );
}
}
/**
* Define which columns to show on this screen.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_columns( $columns = array() ) {
if ( ! is_array( $columns ) || empty( $columns ) ) {
$columns = array();
}
$columns['wc_sc_view_orders'] = __( 'Used in orders', 'woocommerce-smart-coupons' );
return $columns;
}
/**
* Render individual columns.
*
* @param string $column Column ID to render.
* @param int $post_id Post ID being shown.
*/
public function render_columns( $column = '', $post_id = 0 ) {
$this->prepare_row_data( $post_id );
if ( ! $this->object ) {
return;
}
if ( ! empty( $column ) ) {
switch ( $column ) {
case 'wc_sc_view_orders':
$this->render_view_orders_column( $post_id, $this->object );
break;
}
}
}
/**
* Render column: View orders.
*
* @param integer $coupon_id The coupon id.
* @param WC_Coupon $coupon The coupon object.
*/
public function render_view_orders_column( $coupon_id = 0, $coupon = null ) {
if ( $this->is_wc_gte_30() ) {
$usage_count = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_usage_count' ) ) ) ? $coupon->get_usage_count() : 0;
} else {
$usage_count = ( ! empty( $coupon->usage_count ) ) ? $coupon->usage_count : 0;
}
$column_content = '';
if ( ! empty( $usage_count ) ) {
if ( $this->is_wc_gte_30() ) {
$coupon_code = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
} else {
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
$coupon_usage_url = add_query_arg(
array(
's' => $coupon_code,
'post_status' => 'all',
'post_type' => 'shop_order',
),
admin_url( 'edit.php' )
);
$column_content = sprintf( '<a href="%s" target="_blank"><span class="dashicons dashicons-external"></span></a>', esc_url( $coupon_usage_url ) );
} else {
$column_content = '&ndash;';
}
$column_content = apply_filters( 'wc_sc_view_orders_column_content', $column_content, array( 'coupon' => $coupon ) );
echo wp_kses_post( $column_content );
}
}
}
WC_SC_Coupon_Columns::get_instance();

View File

@@ -0,0 +1,528 @@
<?php
/**
* Class to handle feature Coupon Message
*
* @author Ratnakar
* @category Admin
* @package wocommerce-smart-coupons/includes
* @version 2.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupon_Message' ) ) {
/**
* Class WC_SC_Coupon_Message
*/
class WC_SC_Coupon_Message {
/**
* Variable to hold instance of this class
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*
* @since 1.0
*/
private function __construct() {
add_action( 'wc_smart_coupons_actions', array( $this, 'wc_coupon_message_options' ), 10, 2 );
add_action( 'woocommerce_coupon_options_save', array( $this, 'wc_process_coupon_message_meta' ), 10, 2 );
add_action( 'wp_ajax_get_wc_coupon_message', array( $this, 'get_wc_coupon_message' ) );
add_action( 'wp_ajax_nopriv_get_wc_coupon_message', array( $this, 'get_wc_coupon_message' ) );
add_action( 'woocommerce_before_cart_table', array( $this, 'wc_coupon_message_display' ) );
add_action( 'woocommerce_checkout_before_customer_details', array( $this, 'wc_coupon_message_display' ) );
add_action( 'woocommerce_email_after_order_table', array( $this, 'wc_add_coupons_message_in_email' ), null, 3 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_action_meta' ) );
}
/**
* Get single instance of this class
*
* @return this class Singleton object of this class
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Function to add additional fields for coupon
*
* @param integer $coupon_id The coupon id.
* @param WC_Coupon $coupon The coupon object.
* @since 1.0
*/
public function wc_coupon_message_options( $coupon_id = 0, $coupon = null ) {
global $post;
?>
<style type="text/css">
#wc_coupon_message_options #wc_coupon_message_ifr {
height: 100% !important;
}
#wp-wc_coupon_message-wrap {
display: inline-block;
width: 70%;
margin: -3em 0 0 12.5em;
}
.wp_editor_coupon_message {
width: 100%;
}
</style>
<?php
$editor_args = array(
'textarea_name' => 'wc_coupon_message',
'textarea_rows' => 10,
'editor_class' => 'wp_editor_coupon_message',
'media_buttons' => true,
'tinymce' => true,
);
echo '<div id="wc_coupon_message_options" class="options_group smart-coupons-field">';
?>
<p class="form-field wc_coupon_message_row">
<label for="wc_coupon_message"><?php echo esc_html__( 'Display message', 'woocommerce-smart-coupons' ); ?></label>
<?php $wc_coupon_message = $this->get_post_meta( $post->ID, 'wc_coupon_message', true ); ?>
<?php wp_editor( $wc_coupon_message, 'wc_coupon_message', $editor_args ); ?>
</p>
<?php
woocommerce_wp_checkbox(
array(
'id' => 'wc_email_message',
'label' => __( 'Email message?', 'woocommerce-smart-coupons' ),
'description' => __(
'Check this box to include above message in order confirmation email',
'woocommerce-smart-coupons'
),
)
);
echo '</div>';
}
/**
* Function to save coupon plus data in coupon's meta
*
* @since 1.0
*
* @param integer $post_id Coupon's id.
* @param WC_Coupon $coupon Current coupon object.
*/
public function wc_process_coupon_message_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$allowed_html = wp_kses_allowed_html( 'post' );
$additional_allowed_html = array(
'style' => array(),
);
$additional_allowed_html = apply_filters( 'wc_sc_kses_allowed_html_for_coupon_message', $additional_allowed_html, array( 'source' => $this ) );
if ( ! empty( $additional_allowed_html ) ) {
foreach ( $additional_allowed_html as $tag => $attributes ) {
if ( ! empty( $attributes ) && array_key_exists( $tag, $allowed_html ) ) {
$allowed_html[ $tag ] = array_merge( $allowed_html[ $tag ], $attributes );
} else {
$allowed_html[ $tag ] = $attributes;
}
}
}
if ( $this->is_callable( $coupon, 'update_meta_data' ) && $this->is_callable( $coupon, 'save' ) ) {
if ( isset( $_POST['wc_coupon_message'] ) ) { // phpcs:ignore
$coupon->update_meta_data( 'wc_coupon_message', wp_kses( wp_unslash( $_POST['wc_coupon_message'] ), $allowed_html ) ); // phpcs:ignore
}
if ( isset( $_POST['wc_email_message'] ) ) { // phpcs:ignore
$coupon->update_meta_data( 'wc_email_message', wc_clean( wp_unslash( $_POST['wc_email_message'] ) ) ); // phpcs:ignore
} else {
$coupon->update_meta_data( 'wc_email_message', 'no' );
}
$coupon->save();
} else {
if ( isset( $_POST['wc_coupon_message'] ) ) { // phpcs:ignore
update_post_meta( $post_id, 'wc_coupon_message', wp_kses( wp_unslash( $_POST['wc_coupon_message'] ), $allowed_html ) ); // phpcs:ignore
}
if ( isset( $_POST['wc_email_message'] ) ) { // phpcs:ignore
update_post_meta( $post_id, 'wc_email_message', wc_clean( wp_unslash( $_POST['wc_email_message'] ) ) ); // phpcs:ignore
} else {
update_post_meta( $post_id, 'wc_email_message', 'no' );
}
}
}
/**
* Function to print coupon message
*
* @param array $applied_coupons Applied coupons.
*/
public function print_coupon_message( $applied_coupons = array() ) {
if ( empty( $applied_coupons ) ) {
echo '<div class="no_wc_coupon_message"></div>';
return;
}
foreach ( $applied_coupons as $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code );
if ( ! $this->is_valid( $coupon ) ) {
continue;
}
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
}
$wc_coupon_message = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_coupon_message' ) : get_post_meta( $coupon_id, 'wc_coupon_message', true );
if ( empty( $wc_coupon_message ) ) {
continue;
}
?>
<div id="wc_coupon_message_<?php echo esc_attr( $coupon_id ); ?>" class="wc_coupon_message_container">
<div class="wc_coupon_message_body">
<?php
$is_filter_content = apply_filters(
'wc_sc_is_filter_content_coupon_message',
true,
array(
'source' => $this,
'called_by' => current_filter(),
'coupon_object' => $coupon,
)
);
if ( true === $is_filter_content ) {
$wc_coupon_message = apply_filters( 'the_content', $wc_coupon_message );
}
?>
<?php echo wp_kses_post( $wc_coupon_message ); // phpcs:ignore ?>
</div>
</div>
<?php
}
}
/**
* Function to validate applied coupon's additional field which comes from this plugin
*
* @since 1.0
*/
public function wc_coupon_message_display() {
if ( ! is_object( WC() ) || ! is_object( WC()->cart ) || WC()->cart->is_empty() ) {
return;
}
$applied_coupons = WC()->cart->get_applied_coupons();
?>
<div class="wc_coupon_message_wrap" style="padding: 10px 0 10px;">
<?php $this->print_coupon_message( $applied_coupons ); ?>
</div>
<?php
$js = '';
$cart_page_id = absint( get_option( 'woocommerce_cart_page_id' ) );
$checkout_page_id = absint( get_option( 'woocommerce_checkout_page_id' ) );
if ( has_block( 'woocommerce-smart-coupons/available-coupons', $cart_page_id ) || has_block( 'woocommerce-smart-coupons/available-coupons', $checkout_page_id ) ) { // Code to handle apply coupon via blocks.
$js = "
// Check if sc_coupon_message_ajax is undefined
if (typeof sc_coupon_message_ajax === 'undefined') {
var sc_coupon_message_ajax = null;
}
// Define the event listener
function handleCouponMessage() {
clearTimeout(sc_coupon_message_ajax);
sc_coupon_message_ajax = setTimeout(function () {
var xhr = new XMLHttpRequest();
xhr.open('POST', '" . admin_url( 'admin-ajax.php' ) . "', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var response = xhr.responseText;
var wc_coupon_message_wrap = document.querySelector('.wc_coupon_message_wrap');
wc_coupon_message_wrap.innerHTML = '';
if (response !== undefined && response !== '') {
wc_coupon_message_wrap.innerHTML = response;
}
}
};
let data = {
action: 'get_wc_coupon_message',
security: '" . wp_create_nonce( 'wc_coupon_message' ) . "'
};
let formData = '';
for (let key in data) {
formData += key + '=' + data[key] + '&';
}
formData = formData.slice(0, -1); // Remove the trailing '&'
xhr.send(formData);
}, 200);
}
// Add event listeners
document.addEventListener('applied_coupon', handleCouponMessage);
document.addEventListener('removed_coupon', handleCouponMessage);
document.addEventListener('updated_checkout', handleCouponMessage);
";
} else {
if ( is_cart() || is_checkout() ) {
$js = "
if (typeof sc_coupon_message_ajax === 'undefined') {
var sc_coupon_message_ajax = null;
}
jQuery('body').on('applied_coupon removed_coupon updated_checkout', function(){
clearTimeout( sc_coupon_message_ajax );
sc_coupon_message_ajax = setTimeout(function(){
jQuery.ajax({
url: '" . admin_url( 'admin-ajax.php' ) . "',
type: 'POST',
dataType: 'html',
data: {
action: 'get_wc_coupon_message',
security: '" . wp_create_nonce( 'wc_coupon_message' ) . "'
},
success: function( response ) {
jQuery('.wc_coupon_message_wrap').html('');
if ( response != undefined && response != '' ) {
jQuery('.wc_coupon_message_wrap').html( response );
}
}
});
}, 200);
});
";
}
}
if ( ! empty( $js ) ) {
wc_enqueue_js( $js );
}
}
/**
* Function to get coupon messages via ajax
*/
public function get_wc_coupon_message() {
check_ajax_referer( 'wc_coupon_message', 'security' );
$applied_coupons = WC()->cart->get_applied_coupons();
$this->print_coupon_message( $applied_coupons );
die();
}
/**
* Function to add coupon's message in email
*
* @since 1.0
*
* @param WC_Order $order Order's object.
* @param boolean $bool Not used in this function.
* @param boolean $plain_text Not used in this function.
*/
public function wc_add_coupons_message_in_email( $order = null, $bool = false, $plain_text = false ) {
$used_coupons = $this->get_coupon_codes( $order );
if ( count( $used_coupons ) <= 0 ) {
return;
}
$show_coupon_message_title = false;
$coupon_messages = '';
foreach ( $used_coupons as $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code );
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
}
$is_callable_coupon_get_meta = $this->is_callable( $coupon, 'get_meta' );
if ( true === $is_callable_coupon_get_meta ) {
$coupon_message = $coupon->get_meta( 'wc_coupon_message' );
$include_in_email = $coupon->get_meta( 'wc_email_message' );
} else {
$coupon_message = get_post_meta( $coupon_id, 'wc_coupon_message', true );
$include_in_email = get_post_meta( $coupon_id, 'wc_email_message', true );
}
if ( ! empty( $coupon_message ) && 'yes' === $include_in_email ) {
$is_filter_content = apply_filters(
'wc_sc_is_filter_content_coupon_message',
true,
array(
'source' => $this,
'called_by' => current_filter(),
'coupon_object' => $coupon,
'order_object' => $order,
)
);
if ( true === $is_filter_content ) {
$coupon_messages .= apply_filters( 'the_content', $coupon_message );
} else {
$coupon_messages .= $coupon_message;
}
$show_coupon_message_title = true;
}
}
if ( $show_coupon_message_title ) {
?>
<h2><?php echo esc_html__( 'Coupon Message', 'woocommerce-smart-coupons' ); ?></h2>
<?php
echo '<div class="wc_coupon_message_wrap" style="padding: 10px 0 10px;">';
echo wp_kses_post( $coupon_messages ); // phpcs:ignore
echo '</div>';
}
}
/**
* Add meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$cm_headers = array(
'wc_coupon_message' => __( 'Coupon Message', 'woocommerce-smart-coupons' ),
'wc_email_message' => __( 'Is Email Coupon Message', 'woocommerce-smart-coupons' ),
);
return array_merge( $headers, $cm_headers );
}
/**
* Post meta defaults for CM's meta
*
* @param array $defaults Existing postmeta defaults.
* @return array
*/
public function postmeta_defaults( $defaults = array() ) {
$cm_defaults = array(
'wc_coupon_message' => '',
'wc_email_message' => '',
);
return array_merge( $defaults, $cm_defaults );
}
/**
* Add CM's meta with value in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array Modified data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
$data['wc_coupon_message'] = ( ! empty( $post['wc_coupon_message'] ) ) ? wp_kses_post( $post['wc_coupon_message'] ) : '';
$data['wc_email_message'] = ( ! empty( $post['wc_email_message'] ) ) ? wc_clean( wp_unslash( $post['wc_email_message'] ) ) : 'no';
return $data;
}
/**
* Make meta data of SC CM, protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected, $meta_key, $meta_type ) {
$sc_meta = array(
'wc_coupon_message' => '',
'wc_email_message' => '',
);
if ( in_array( $meta_key, $sc_meta, true ) ) {
return true;
}
return $protected;
}
/**
* Function to copy CM meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_action_meta( $args = array() ) {
$new_coupon_id = ( ! empty( $args['new_coupon_id'] ) ) ? absint( $args['new_coupon_id'] ) : 0;
$coupon = ( ! empty( $args['ref_coupon'] ) ) ? $args['ref_coupon'] : false;
if ( empty( $new_coupon_id ) || empty( $coupon ) ) {
return;
}
$new_coupon = new WC_Coupon( $new_coupon_id );
if ( $this->is_callable( $new_coupon, 'get_meta' ) && $this->is_callable( $new_coupon, 'update_meta_data' ) && $this->is_callable( $new_coupon, 'save' ) ) {
$coupon_message = $coupon->get_meta( 'wc_coupon_message' );
$email_message = $coupon->get_meta( 'wc_email_message' );
$new_coupon->update_meta_data( 'wc_coupon_message', wp_filter_post_kses( $coupon_message ) );
$new_coupon->update_meta_data( 'wc_email_message', $email_message );
} else {
$old_coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$coupon_message = get_post_meta( $old_coupon_id, 'wc_coupon_message', true );
$email_message = get_post_meta( $old_coupon_id, 'wc_email_message', true );
update_post_meta( $new_coupon_id, 'wc_coupon_message', wp_filter_post_kses( $coupon_message ) );
update_post_meta( $new_coupon_id, 'wc_email_message', $email_message );
}
}
}
}
WC_SC_Coupon_Message::get_instance();

View File

@@ -0,0 +1,454 @@
<?php
/**
* Coupon parser during import & export
*
* @author StoreApps
* @since 3.3.0
* @version 1.5.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupon_Parser' ) ) {
/**
* Class to parse values for WC_Coupon for importing
*/
class WC_SC_Coupon_Parser {
/**
* The post type
*
* @var string $post_type
*/
public $post_type;
/**
* Reserved fields
*
* @var array $reserved_fields
*/
public $reserved_fields; // Fields we map/handle (not custom fields).
/**
* POst defaults
*
* @var array $post_defaults
*/
public $post_defaults; // Default post data.
/**
* Postmeta defaults
*
* @var array $postmeta_defaults
*/
public $postmeta_defaults; // default post meta.
/**
* Term defaults
*
* @var array $term_defaults
*/
public $term_defaults; // default term data.
/**
* Row number
*
* @var int $row
*/
public $row;
/**
* Constructor
*
* @param string $post_type The post type.
*/
public function __construct( $post_type = 'shop_coupon' ) {
$this->post_type = $post_type;
$this->reserved_fields = array(
'id',
'post_id',
'post_type',
'menu_order',
'postmeta',
'post_status',
'post_title',
'post_name',
'comment_status',
'post_date',
'post_date_gmt',
'post_content',
'post_excerpt',
'post_parent',
'post_password',
'discount_type',
'coupon_amount',
'free_shipping',
'expiry_date',
'minimum_amount',
'maximum_amount',
'individual_use',
'exclude_sale_items',
'product_ids',
'exclude_product_ids',
'product_categories',
'exclude_product_categories',
'customer_email',
'usage_limit',
'usage_limit_per_user',
'limit_usage_to_x_items',
'usage_count',
'_used_by',
);
$this->post_defaults = array(
'post_type' => $this->post_type,
'menu_order' => '',
'postmeta' => array(),
'post_status' => 'publish',
'post_title' => '',
'post_name' => '',
'comment_status' => 'closed',
'post_date' => '',
'post_date_gmt' => '',
'post_content' => '',
'post_excerpt' => '',
'post_parent' => 0,
'post_password' => '',
'post_author' => get_current_user_id(),
);
$this->postmeta_defaults = apply_filters(
'smart_coupons_parser_postmeta_defaults',
array(
'discount_type' => 'fixed_cart',
'coupon_amount' => '',
'free_shipping' => '',
'expiry_date' => '',
'sc_coupon_validity' => '',
'validity_suffix' => '',
'auto_generate_coupon' => '',
'coupon_title_prefix' => '',
'coupon_title_suffix' => '',
'is_pick_price_of_product' => '',
'minimum_amount' => '',
'maximum_amount' => '',
'individual_use' => '',
'exclude_sale_items' => '',
'product_ids' => '',
'exclude_product_ids' => '',
'product_categories' => '',
'exclude_product_categories' => '',
'customer_email' => '',
'sc_disable_email_restriction' => '',
'usage_limit' => '',
'usage_limit_per_user' => '',
'limit_usage_to_x_items' => '',
'sc_is_visible_storewide' => '',
'usage_count' => '',
'_used_by' => '',
'sc_restrict_to_new_user' => '',
'wc_sc_max_discount' => '',
)
);
$this->term_defaults = array(
'sc_coupon_category' => '',
);
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Format data passed from CSV
*
* @param array $data The data to format.
* @param string $enc encoding The encoding.
*/
public function format_data_from_csv( $data, $enc ) {
return ( 'UTF-8' === $enc ) ? $data : utf8_encode( $data );
}
/**
* Parse data
*
* @param string $file Imported file.
* @return array parsed data with headers
*/
public function parse_data( $file ) {
// Set locale.
$enc = $this->mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
if ( $enc ) {
setlocale( LC_ALL, 'en_US.' . $enc );
}
if ( ! $this->is_php_gte( '8.0.0' ) ) {
ini_set( 'auto_detect_line_endings', true ); // phpcs:ignore
}
$parsed_data = array();
$handle = fopen( $file, 'r' ); // phpcs:ignore
// Put all CSV data into an associative array.
if ( false !== $handle ) {
$header = fgetcsv( $handle, 0 );
while ( false !== ( $postmeta = fgetcsv( $handle, 0 ) ) ) { // phpcs:ignore
$row = array();
foreach ( $header as $key => $heading ) {
$s_heading = strtolower( $heading );
$row[ $s_heading ] = ( isset( $postmeta[ $key ] ) ) ? $this->format_data_from_csv( stripslashes( $postmeta[ $key ] ), $enc ) : '';
$raw_headers[ $s_heading ] = $heading;
}
$parsed_data[] = $row;
unset( $postmeta, $row );
}
fclose( $handle ); // phpcs:ignore
}
return array( $parsed_data, $raw_headers );
}
/**
* Parse data one row at a time
*
* @param boolean $file_handler CSV file handler.
* @param array $header CSV header meta column name.
* @param integer $file_position file pointer posistion to read from.
* @param string $encoding Character encoding.
* @return array $result parsed data with current file pointer position
*/
public function parse_data_by_row( $file_handler = false, $header = array(), $file_position = 0, $encoding = '' ) {
$parsed_csv_data = array();
$reading_completed = false;
if ( false !== $file_handler ) {
if ( $file_position > 0 ) {
fseek( $file_handler, (int) $file_position );
}
if ( false !== ( $postmeta = fgetcsv( $file_handler, 0 ) ) ) { // phpcs:ignore
$row = array();
foreach ( $header as $key => $heading ) {
$s_heading = strtolower( $heading );
// Put all CSV data into an associative array by row.
$row[ $s_heading ] = ( isset( $postmeta[ $key ] ) ) ? $this->format_data_from_csv( stripslashes( $postmeta[ $key ] ), $encoding ) : '';
}
$parsed_csv_data = $row;
unset( $postmeta, $row );
} else {
$reading_completed = true;
}
$file_position = ftell( $file_handler );
}
$result = array(
'parsed_csv_data' => $parsed_csv_data,
'file_position' => $file_position,
'reading_completed' => $reading_completed,
);
return $result;
}
/**
* Parse coupon
*
* @param array $item The imported item.
* @return array $coupon
*/
public function parse_coupon( $item ) {
global $wc_csv_coupon_import;
$this->row++;
$postmeta = array();
$term_data = array();
$coupon = array();
$post_id = ( ! empty( $item['id'] ) ) ? absint( $item['id'] ) : 0;
$post_id = ( ! empty( $item['post_id'] ) ) ? absint( $item['post_id'] ) : $post_id;
$product['post_id'] = $post_id;
// Get post fields.
foreach ( $this->post_defaults as $column => $default ) {
if ( isset( $item[ $column ] ) ) {
$product[ $column ] = $item[ $column ];
}
}
// Get custom fields.
foreach ( $this->postmeta_defaults as $column => $default ) {
if ( isset( $item[ $column ] ) ) {
$postmeta[ $column ] = (string) $item[ $column ];
} elseif ( isset( $item[ '_' . $column ] ) ) {
$postmeta[ $column ] = (string) $item[ '_' . $column ];
}
}
// Get term fields.
foreach ( $this->term_defaults as $column => $default ) {
if ( isset( $item[ $column ] ) ) {
$term_data[ $column ] = $item[ $column ];
}
}
// Merge post meta with defaults.
$coupon = wp_parse_args( $product, $this->post_defaults );
$postmeta = wp_parse_args( $postmeta, $this->postmeta_defaults );
$term_data = wp_parse_args( $term_data, $this->term_defaults );
$all_discount_types = wc_get_coupon_types();
if ( ! empty( $postmeta['discount_type'] ) ) {
$discount_type = __( $postmeta['discount_type'], 'woocommerce' ); // phpcs:ignore
} else {
if ( $this->is_wc_gte_30() ) {
$discount_type = __( 'Percentage discount', 'woocommerce' );
} else {
$discount_type = __( 'Cart % Discount', 'woocommerce' );
}
}
$discount_type = ( ! empty( $discount_type ) && in_array( $discount_type, $all_discount_types, true ) ) ? $discount_type : $postmeta['discount_type'];
// discount types.
if ( ! empty( $discount_type ) ) {
if ( in_array( $discount_type, $all_discount_types, true ) ) {
$postmeta['discount_type'] = array_search( $discount_type, $all_discount_types, true );
}
if ( empty( $postmeta['discount_type'] ) ) {
$postmeta['discount_type'] = 'percent';
}
}
// product_ids.
if ( isset( $postmeta['product_ids'] ) && ! is_array( $postmeta['product_ids'] ) ) {
$ids = array_filter( array_map( 'trim', explode( '|', $postmeta['product_ids'] ) ) );
$ids = implode( ',', $ids );
$postmeta['product_ids'] = $ids;
}
// exclude_product_ids.
if ( isset( $postmeta['exclude_product_ids'] ) && ! is_array( $postmeta['exclude_product_ids'] ) ) {
$ids = array_filter( array_map( 'trim', explode( '|', $postmeta['exclude_product_ids'] ) ) );
$ids = implode( ',', $ids );
$postmeta['exclude_product_ids'] = $ids;
}
// product_categories.
if ( isset( $postmeta['product_categories'] ) && ! is_array( $postmeta['product_categories'] ) ) {
$ids = array_filter( array_map( 'trim', explode( '|', $postmeta['product_categories'] ) ) );
$postmeta['product_categories'] = $ids;
}
// exclude_product_categories.
if ( isset( $postmeta['exclude_product_categories'] ) && ! is_array( $postmeta['exclude_product_categories'] ) ) {
$ids = array_filter( array_map( 'trim', explode( '|', $postmeta['exclude_product_categories'] ) ) );
$postmeta['exclude_product_categories'] = $ids;
}
// customer_email.
if ( isset( $postmeta['customer_email'] ) && ! is_array( $postmeta['customer_email'] ) ) {
$email_ids = array_filter( array_map( 'trim', explode( ',', $postmeta['customer_email'] ) ) );
$postmeta['customer_email'] = $email_ids;
}
// expiry date.
if ( isset( $postmeta['expiry_date'] ) ) {
$timestamp_expiry_date = '';
if ( ! empty( $postmeta['expiry_date'] ) ) {
$timestamp_expiry_date = ( function_exists( 'wc_string_to_timestamp' ) ) ? wc_string_to_timestamp( $postmeta['expiry_date'] ) : 0;
}
if ( ! empty( $postmeta['expiry_date'] ) && empty( $timestamp_expiry_date ) ) {
/* translators: 1. Coupon code 2. Expiry date */
$this->log( 'error', sprintf( __( 'Incorrect format for expiry date of coupon "%1$s". Entered date is %2$s. Expected date format: YYYY-MM-DD', 'woocommerce-smart-coupons' ), $coupon['post_title'], $postmeta['expiry_date'] ) );
}
$postmeta['expiry_date'] = ( ! empty( $timestamp_expiry_date ) ) ? gmdate( 'Y-m-d', $timestamp_expiry_date ) : '';
}
// usage count.
if ( isset( $postmeta['usage_count'] ) ) {
$postmeta['usage_count'] = ( ! empty( $postmeta['usage_count'] ) ) ? $postmeta['usage_count'] : 0;
}
// used_by.
if ( isset( $postmeta['_used_by'] ) ) {
$postmeta['_used_by'] = ( ! empty( $postmeta['_used_by'] ) ) ? $postmeta['_used_by'] : '';
}
// Put set core product postmeta into product array.
foreach ( $postmeta as $key => $value ) {
$coupon['postmeta'][] = array(
'key' => esc_attr( $key ),
'value' => $value,
);
}
// term data.
foreach ( $term_data as $key => $value ) {
$coupon['term_data'][] = array(
'key' => esc_attr( $key ),
'value' => $value,
);
}
unset( $item, $postmeta );
return $coupon;
}
}
}

View File

@@ -0,0 +1,862 @@
<?php
/**
* Processing of smart coupons refund
*
* @author StoreApps
* @since 5.2.0
* @version 2.1.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupon_Refund_Process' ) ) {
/**
* Class for handling processes of smart coupons refund
*/
class WC_SC_Coupon_Refund_Process {
/**
* Variable to hold instance of WC_SC_Coupon_Refund_Process
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_admin_order_items_after_shipping', array( $this, 'render_used_store_credits_details' ) );
add_action( 'woocommerce_admin_order_items_after_refunds', array( $this, 'render_refunded_store_credits_details' ) );
add_filter( 'woocommerce_order_fully_refunded_status', array( $this, 'update_fully_refunded_status' ), 10, 3 );
add_action( 'wp_ajax_wc_sc_refund_store_credit', array( $this, 'wc_sc_refund_store_credit' ) );
add_action( 'wp_ajax_wc_sc_revoke_refunded_store_credit', array( $this, 'wc_sc_revoke_refunded_store_credit' ) );
}
/**
* Get single instance of WC_SC_Coupon_Process
*
* @return WC_SC_Coupon_Process Singleton object of WC_SC_Coupon_Process
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Render smart coupon UI in order page
*
* @param int $order_id order id.
* @return void html of smart coupon UI
*/
public function render_used_store_credits_details( $order_id = 0 ) {
?>
<style type="text/css">
#order_sc_store_credit_line_items tbody tr:first-child td {
border-top: 8px solid #f8f8f8;
}
</style>
<script type="text/javascript">
jQuery(function ($) {
/**
* Auto fill and remove - refund store credit coupon amount
*/
$(document).on('change', '.sc_auto_fill_refund', function () {
if ($(this).prop("checked") === true) {
$('.sc_store_credit').each(function (index, element) {
let used_sc = $(element).data("order_used_sc");
let order_used_sc_tax = $(element).data("order_used_sc_tax");
$(this).find('.refund_used_sc').val(used_sc);
$(this).find('.refund_used_sc_tax').val(order_used_sc_tax);
});
} else {
$('.refund_used_sc').val(0);
$('.refund_used_sc_tax').val(0);
}
});
/**
* Process store credit refund
*/
$('#woocommerce-order-items').on('click', 'button.do-api-refund, button.do-manual-refund', function () {
var sc_line_item = {};
$('.sc_store_credit').each(function (index, element) {
let sc_line_item_data = {};
let used_coupon_id = $(this).data("used_sc_id");
let order_id = $(this).data("used_sc_order_id");
let sc_refund_amount = $(this).find('.refund_used_sc').val();
let sc_refund_tax_amount = $(this).find('.refund_used_sc_tax').val();
let order_used_total_amount = $(this).find('.order_used_total_sc_amount').val();
let order_sc_item_id = $(this).find('.order_sc_item_id').val();
if (order_sc_item_id !== 0 || order_sc_item_id !== null || order_sc_item_id !== undefined) {
sc_line_item_data['coupon_id'] = used_coupon_id;
sc_line_item_data['refund_amount'] = sc_refund_amount;
sc_line_item_data['order_used_total_amount'] = order_used_total_amount;
sc_line_item_data['order_sc_item_id'] = order_sc_item_id;
sc_line_item_data['sc_order_id'] = order_id;
sc_line_item_data['order_sc_refund_tax_amount'] = sc_refund_tax_amount;
sc_line_item [order_sc_item_id] = sc_line_item_data;
}
});
let sc_refund_nonce = $('#sc_refund_nonce').val();
var data = {
action: 'wc_sc_refund_store_credit',
line_items: JSON.stringify(sc_line_item, null, ''),
security: sc_refund_nonce
};
$.ajax({
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
type: 'POST',
data: data
});
});
});
</script>
<tbody id="order_sc_store_credit_line_items">
<?php
$order = ( function_exists( 'wc_get_order' ) && ! empty( $order_id ) ) ? wc_get_order( $order_id ) : null;
$order_total = $this->is_callable( $order, 'get_total' ) ? $order->get_total() : 0;
$order_items = ( is_object( $order ) && $this->is_callable( $order, 'get_items' ) ) ? $order->get_items( 'coupon' ) : array();
$tax_data = ( function_exists( 'wc_tax_enabled' ) && wc_tax_enabled() && is_object( $order ) && $this->is_callable( $order, 'get_taxes' ) ) ? $order->get_taxes() : array();
if ( ! class_exists( 'WC_SC_Order_Fields' ) ) {
include_once 'class-wc-sc-order-fields.php';
}
$sc_order_fields = WC_SC_Order_Fields::get_instance();
$total_credit_used_in_order = $sc_order_fields->get_total_credit_used_in_order( $order );
$i = 1;
if ( ! empty( $order_items ) ) {
$is_apply_before_tax = get_option( 'woocommerce_smart_coupon_apply_before_tax', 'no' );
$is_readonly = ( 'yes' !== $is_apply_before_tax ) ? true : false;
$allow_custom_refund_amount = apply_filters(
'wc_sc_allow_custom_refund_amount',
( false === $is_readonly ),
array(
'source' => $this,
'order_obj' => $order,
)
);
$is_old_sc_order = $this->is_old_sc_order( $order_id );
$item_titles = array_map(
function( $item ) {
return ( $this->is_callable( $item, 'get_name' ) ) ? $item->get_name() : '';
},
$order_items
);
$posts = $this->get_post_by_title( $item_titles, OBJECT, 'shop_coupon' );
foreach ( $order_items as $item_id => $item ) {
$order_discount_amount = $sc_refunded_discount = $sc_refunded_discount_tax = $order_discount_tax_amount = 0; // phpcs:ignore
$coupon_code = ( $this->is_callable( $item, 'get_name' ) ) ? $item->get_name() : '';
$sanitized_coupon_code = sanitize_title( $coupon_code ); // The generated string will be checked in an array key to locate post object.
$coupon_post_obj = ( ! empty( $posts[ $sanitized_coupon_code ] ) ) ? $posts[ $sanitized_coupon_code ] : null;
$coupon_id = isset( $coupon_post_obj->ID ) ? $coupon_post_obj->ID : '';
$coupon_title = isset( $coupon_post_obj->post_title ) ? $coupon_post_obj->post_title : '';
$coupon = new WC_Coupon( $coupon_id );
if ( is_a( $coupon, 'WC_Coupon' ) ) {
if ( $coupon->is_type( 'smart_coupon' ) ) {
if ( 1 === $i ) {
?>
<tr class="sc_store_credit_head refund">
<td class="">
<div class="refund" style="display: none; padding-top: 15px;">
<svg xmlns="http://www.w3.org/2000/svg" style="color: #b5b5b5;" fill="none" viewBox="0 0 40 40" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M15 5v2m0 4v2m0 4v2M5 5a2 2 0 00-2 2v3a2 2 0 110 4v3a2 2 0 002 2h14a2 2 0 002-2v-3a2 2 0 110-4V7a2 2 0 00-2-2H5z">
</path>
</svg>
</div>
</td>
<td>
<div class="refund" style="display: none; padding-top: 15px;">
<div class="view"><?php echo esc_html__( 'Refund to Store Credit', 'woocommerce-smart-coupons' ); ?></div>
</div>
</td>
<td>
</td>
<td>
<input type="hidden" name="sc_refund_nonce" id="sc_refund_nonce" value="<?php echo esc_attr( wp_create_nonce( 'sc_refund_nonce' ) ); ?>">
</td>
<td colspan="2">
<?php if ( true === $is_old_sc_order || 'yes' === $is_apply_before_tax ) { ?>
<div class="refund" style="display: none; padding-top: 15px;">
<input type="checkbox" name="sc_auto_fill_refund" class="sc_auto_fill_refund" id="sc_auto_fill_refund">
<label for="sc_auto_fill_refund"><?php echo esc_html_e( 'Auto-fill refund amount', 'woocommerce-smart-coupons' ); ?></label>
</div>
<?php } ?>
</td>
<?php
if ( ! empty( $tax_data ) ) {
$tax_data_count = count( $tax_data );
?>
<td colspan="<?php echo esc_attr( ( $tax_data_count ) ); ?>">
</td>
<?php
}
?>
</tr>
<?php
}
$i++;
if ( is_callable( array( $this, 'get_order_item_meta' ) ) ) {
$order_discount_amount = (float) $this->get_order_item_meta( $item_id, 'discount_amount', true );
$sc_refunded_discount = (float) $this->get_order_item_meta( $item_id, 'sc_refunded_discount', true );
$sc_refunded_discount_tax = (float) $this->get_order_item_meta( $item_id, 'sc_refunded_discount_tax', true );
$order_discount_tax_amount = (float) $this->get_order_item_meta( $item_id, 'discount_amount_tax', true );
}
?>
<tr class="sc_store_credit" data-order_used_sc="<?php echo esc_attr( $order_discount_amount ); ?>"
data-used_sc_id="<?php echo esc_attr( $coupon_id ); ?>"
data-used_sc_order_id="<?php echo esc_attr( $order_id ); ?>"
data-order_used_sc_tax="<?php echo esc_attr( $order_discount_tax_amount ); ?>">
<td class="thumb">
<div>
<svg xmlns="http://www.w3.org/2000/svg" style="color: #b5b5b5;" fill="none" viewBox="0 0 40 40" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M15 5v2m0 4v2m0 4v2M5 5a2 2 0 00-2 2v3a2 2 0 110 4v3a2 2 0 002 2h14a2 2 0 002-2v-3a2 2 0 110-4V7a2 2 0 00-2-2H5z">
</path>
</svg>
</div>
</td>
<td class="name">
<div class="view">
<?php
echo esc_html( $coupon_title ); // phpcs:ignore
?>
</div>
</td>
<td class="item_cost" width="1%">&nbsp;</td>
<td class="quantity" width="1%">&nbsp;</td>
<td class="line_cost" width="1%">
<div class="view">
<?php
echo wp_kses_post(
wc_price( $order_discount_amount )
);
if ( ! empty( $sc_refunded_discount ) ) {
?>
<small class="refunded"><?php echo wp_kses_post( wc_price( $sc_refunded_discount ) ); ?></small>
<?php
}
$max_refund_limit = $order_discount_amount - $sc_refunded_discount;
?>
</div>
<div class="edit" style="display: none;">
<input type="text" name="sc_store_credit_cost[<?php echo esc_attr( $coupon_id ); ?>]" placeholder="0" value="<?php echo esc_attr( $order_discount_amount ); ?>" class="sc_line_total wc_input_price">
</div>
<?php if ( $sc_refunded_discount < $order_discount_amount ) { ?>
<div class="refund" style="display: none;">
<input type="text" name="refund_sc_store_credit_line_total[<?php echo esc_attr( $coupon_id ); ?>]" placeholder="0" class="refund_used_sc wc_input_price" max="<?php echo esc_attr( $max_refund_limit ); ?>" <?php ( ( false === $allow_custom_refund_amount ) ? esc_attr_e( 'readonly' ) : '' ); ?>>
<input type="hidden" name="order_used_total_sc_amount[<?php echo esc_attr( $coupon_id ); ?>]" value="<?php echo esc_attr( $order_discount_amount ); ?>" class="order_used_total_sc_amount">
<input type="hidden" name="order_used_item_id[<?php echo esc_attr( $item_id ); ?>]" value="<?php echo esc_attr( $item_id ); ?>" class="order_sc_item_id">
</div>
<?php } ?>
</td>
<?php
if ( ! empty( $tax_data ) ) {
$tax_data_count = count( $tax_data );
?>
<td class="line_tax" width="1%">
<div class="view">
<?php
echo wp_kses_post(
wc_price( $order_discount_tax_amount )
);
if ( ! empty( $sc_refunded_discount_tax ) ) {
?>
<small class="refunded"><?php echo wp_kses_post( wc_price( $sc_refunded_discount_tax ) ); ?></small>
<?php
}
$max_refund_tax_limit = $order_discount_tax_amount - $sc_refunded_discount_tax;
?>
</div>
<div class="edit" style="display: none;">
<input type="text" name="sc_store_credit_cost[<?php echo esc_attr( $coupon_id ); ?>]" placeholder="0" value="<?php echo esc_attr( $order_discount_tax_amount ); ?>" class="sc_line_total wc_input_price">
</div>
<?php if ( $sc_refunded_discount_tax < $order_discount_tax_amount ) { ?>
<div class="refund" style="display: none;">
<input type="text" name="refund_sc_store_credit_line_total[<?php echo esc_attr( $coupon_id ); ?>]" placeholder="0" class="refund_used_sc_tax wc_input_price" max="<?php echo esc_attr( $max_refund_tax_limit ); ?>" <?php ( ( false === $allow_custom_refund_amount ) ? esc_attr_e( 'readonly' ) : '' ); ?>>
</div>
<?php } ?>
</td>
<?php if ( $tax_data_count > 1 ) { ?>
<td colspan="<?php echo esc_attr( ( $tax_data_count - 1 ) ); ?>"></td>
<?php } ?>
<?php } ?>
<td class="wc-order-edit-line-item">
</td>
</tr>
<?php
}
}
}
}
?>
</tbody>
<?php if ( ! $this->is_old_sc_order( $order_id ) && $total_credit_used_in_order > 0 ) { ?>
<script type="text/javascript">
jQuery(function(){
function wc_sc_reload_refund_amount() {
var order_total = '<?php echo esc_html( $order_total ); ?>';
var refund_amount = jQuery('#refund_amount').val();
var wc_sc_refund_line_total = 0;
var wc_sc_refund_line_tax = 0;
jQuery('.line_cost .refund .refund_line_total').each(function() {
wc_sc_refund_line_unit_total = accounting.unformat( jQuery(this).val(), woocommerce_admin.mon_decimal_point );
wc_sc_refund_line_total += wc_sc_refund_line_unit_total;
});
jQuery('.line_tax .refund .refund_line_tax').each(function() {
wc_sc_refund_line_unit_tax = accounting.unformat( jQuery(this).val(), woocommerce_admin.mon_decimal_point );
wc_sc_refund_line_tax += wc_sc_refund_line_unit_tax;
});
jQuery('.refund_used_sc').each(function(){
var max_limit = accounting.unformat( jQuery(this).attr('max') );
wc_sc_refund_line_total = accounting.unformat( wc_sc_refund_line_total, woocommerce_admin.mon_decimal_point );
var new_refund_amount = Math.min( wc_sc_refund_line_total, max_limit );
jQuery(this).val(
accounting.formatNumber(
new_refund_amount,
woocommerce_admin_meta_boxes.currency_format_num_decimals,
'',
woocommerce_admin.mon_decimal_point
)
);
wc_sc_refund_line_total -= new_refund_amount;
});
jQuery('.refund_used_sc_tax').each(function(){
var max_limit = accounting.unformat( jQuery(this).attr('max') );
wc_sc_refund_line_tax = accounting.unformat( wc_sc_refund_line_tax, woocommerce_admin.mon_decimal_point );
var new_refund_amount = Math.min( wc_sc_refund_line_tax, max_limit );
jQuery(this).val(
accounting.formatNumber(
new_refund_amount,
woocommerce_admin_meta_boxes.currency_format_num_decimals,
'',
woocommerce_admin.mon_decimal_point
)
);
wc_sc_refund_line_tax -= new_refund_amount;
});
refund_amount = wc_sc_refund_line_total + wc_sc_refund_line_tax;
if ( refund_amount > 0 ) {
refund_amount = Math.min(refund_amount, order_total);
}
jQuery('button.do-api-refund, button.do-manual-refund').find('.wc-order-refund-amount .amount' ).text( accounting.formatMoney( refund_amount, {
symbol: woocommerce_admin_meta_boxes.currency_format_symbol,
decimal: woocommerce_admin_meta_boxes.currency_format_decimal_sep,
thousand: woocommerce_admin_meta_boxes.currency_format_thousand_sep,
precision: woocommerce_admin_meta_boxes.currency_format_num_decimals,
format: woocommerce_admin_meta_boxes.currency_format
} ) );
if ( refund_amount <= 0 ) {
jQuery('#refund_amount').val('');
jQuery('button.do-api-refund').hide();
} else {
jQuery('#refund_amount').val(
accounting.formatNumber(
refund_amount,
woocommerce_admin_meta_boxes.currency_format_num_decimals,
'',
woocommerce_admin.mon_decimal_point
)
);
jQuery('button.do-api-refund').show();
}
}
jQuery(document).on('change', '#refund_amount', function(){
wc_sc_reload_refund_amount();
});
});
</script>
<?php } ?>
<?php
}
/**
* Refund store credit coupon
*
* @return void add refund store credit to the coupon
*/
public function wc_sc_refund_store_credit() {
global $woocommerce_smart_coupon;
$nonce_token = ! empty( $_POST['security'] ) ? $_POST['security'] : ''; // phpcs:ignore
if ( wp_verify_nonce( wp_unslash( $nonce_token ), 'sc_refund_nonce' ) ) {
$response = array();
$line_items = isset( $_POST['line_items'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['line_items'] ) ), true ) : array();
if ( ! empty( $line_items ) ) {
$order = null;
foreach ( $line_items as $line_item ) {
$total_refunded = $total_refunded_tax = $order_discount_amount = $refunded_amount = $refunded_tax_amount = $order_discount_tax_amount = 0; // phpcs:ignore
$smart_coupon_id = ( ! empty( $line_item['coupon_id'] ) ) ? $line_item['coupon_id'] : 0;
$refund_amount = ( ! empty( $line_item['refund_amount'] ) ) ? wc_format_decimal( $line_item['refund_amount'] ) : 0;
$item_id = ( ! empty( $line_item['order_sc_item_id'] ) ) ? $line_item['order_sc_item_id'] : 0;
$order_sc_refund_tax_amount = ( ! empty( $line_item['order_sc_refund_tax_amount'] ) ) ? wc_format_decimal( $line_item['order_sc_refund_tax_amount'] ) : 0;
$order_id = ( ! empty( $line_item['sc_order_id'] ) ) ? $line_item['sc_order_id'] : 0;
$order = ( ! is_a( $order, 'WC_Order' ) ) ? wc_get_order( $order_id ) : $order;
if ( is_callable( array( $this, 'get_order_item_meta' ) ) ) {
$order_discount_amount = $this->get_order_item_meta( $item_id, 'discount_amount', true );
$refunded_amount = $this->get_order_item_meta( $item_id, 'sc_refunded_discount', true );
$refunded_tax_amount = $this->get_order_item_meta( $item_id, 'sc_refunded_discount_tax', true );
$order_discount_tax_amount = $this->get_order_item_meta( $item_id, 'discount_amount_tax', true );
}
if ( floatval( $order_discount_amount ) === floatval( $refunded_amount ) && floatval( $order_discount_tax_amount ) === floatval( $refunded_tax_amount ) ) {
continue;
}
if ( $refunded_amount ) {
$total_refunded = $refund_amount + $refunded_amount;
}
if ( $refunded_tax_amount ) {
$total_refunded_tax = $order_sc_refund_tax_amount + $refunded_tax_amount;
}
if ( $order_discount_amount >= $refund_amount && $order_discount_amount >= $total_refunded && $order_discount_tax_amount >= $order_sc_refund_tax_amount && $order_discount_tax_amount >= $total_refunded_tax && ! empty( $smart_coupon_id ) ) {
$coupon = new WC_Coupon( $smart_coupon_id );
if ( is_a( $coupon, 'WC_Coupon' ) ) {
if ( $this->is_wc_gte_30() ) {
$discount_type = ( is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
} else {
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
}
$coupon_amount = $this->get_amount( $coupon, true, $order );
if ( 'smart_coupon' === $discount_type && is_numeric( $refund_amount ) && is_numeric( $order_sc_refund_tax_amount ) ) {
$amount = $coupon_amount + $refund_amount + $order_sc_refund_tax_amount;
$this->update_post_meta( $smart_coupon_id, 'coupon_amount', $amount, true, $order );
$user = ( function_exists( 'get_current_user_id' ) ) ? get_current_user_id() : 0;
$local_time = ( function_exists( 'current_datetime' ) ) ? current_datetime() : '';
$get_timestamp = ( is_object( $local_time ) && is_callable( array( $local_time, 'getTimestamp' ) ) ) ? $local_time->getTimestamp() : '';
$get_offset = ( is_object( $local_time ) && is_callable( array( $local_time, 'getOffset' ) ) ) ? $local_time->getOffset() : '';
$current_time_stamp = $get_timestamp + $get_offset;
if ( 0 < $total_refunded ) {
$refund_amount = $total_refunded;
}
if ( 0 < $total_refunded_tax ) {
$order_sc_refund_tax_amount = $total_refunded_tax;
}
if ( is_callable( array( $this, 'update_order_item_meta' ) ) ) {
$this->update_order_item_meta( $item_id, 'sc_refunded_discount_tax', $order_sc_refund_tax_amount );
$this->update_order_item_meta( $item_id, 'sc_refunded_discount', $refund_amount );
$this->update_order_item_meta( $item_id, 'sc_refunded_user_id', $user );
$this->update_order_item_meta( $item_id, 'sc_refunded_timestamp', $current_time_stamp );
$this->update_order_item_meta( $item_id, 'sc_refunded_coupon_id', $smart_coupon_id );
$message = __( 'Successfully updated store credit refund details.', 'woocommerce-smart-coupons' );
} else {
$message = __( 'Failed to update store credit refund details.', 'woocommerce-smart-coupons' );
$woocommerce_smart_coupon->log( 'notice', $message . ' ' . __FILE__ . ' ' . __LINE__ );
}
$response['message'] = $message;
}
}
}
}
}
wp_send_json_success( $response );
} else {
$response['message'] = __( 'Nonce verification failed for action "wc_sc_refund_store_credit".', 'woocommerce-smart-coupons' );
wp_send_json_error( $response );
}
}
/**
* Render refund store credit UI in order page
*
* @param int $order_id order id.
* @return void revoke refund html
*/
public function render_refunded_store_credits_details( $order_id ) {
global $store_credit_label;
?>
<style type="text/css">
#woocommerce-order-items .wc-order-edit-line-item-actions .delete_wc_sc_refund::before {
font-family: Dashicons;
font-weight: 400;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
text-indent: 0px;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
text-align: center;
content: "";
position: relative;
font-variant: normal;
margin: 0px;
color: #a00;
}
</style>
<script type="text/javascript">
jQuery(function ($) {
/**
* Process store credit revoke refund
*/
var wc_sc_meta_boxes_order_items = {
block: function () {
$('#woocommerce-order-items').block({
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
});
},
};
$('#woocommerce-order-items').on('click', '.delete_wc_sc_refund', function () {
var confirm_message = '<?php esc_html_e( 'Are you sure you wish to delete this refund? This action cannot be undone.', 'woocommerce-smart-coupons' ); ?>';
if (confirm(confirm_message)) {
let sc_line_item_data = {};
let wc_sc_refunded_id = $(this).parents('.wc_sc_refunded').data("wc_sc_refunded_id");
let order_id = $(this).parents('.wc_sc_refunded').data("wc_sc_order_id");
let wc_sc_id = $(this).parents('.wc_sc_refunded').data("wc_sc_coupon_id");
let wc_sc_refunded_amount = $(this).parents('.wc_sc_refunded').data("wc_sc_refunded_amount");
let wc_sc_refunded_amount_tax = $(this).parents('.wc_sc_refunded').data("wc_sc_refunded_amount_tax");
if (wc_sc_refunded_id !== 0 || wc_sc_refunded_id !== null || wc_sc_refunded_id !== undefined) {
sc_line_item_data['coupon_id'] = wc_sc_id;
sc_line_item_data['refund_amount'] = wc_sc_refunded_amount;
sc_line_item_data['refund_amount_tax'] = wc_sc_refunded_amount_tax;
sc_line_item_data['wc_sc_refunded_id'] = wc_sc_refunded_id;
sc_line_item_data['wc_sc_order_id'] = order_id;
}
let sc_revoke_refund_nonce = $('#sc_revoke_refund_nonce').val();
var data = {
action: 'wc_sc_revoke_refunded_store_credit',
line_items: JSON.stringify(sc_line_item_data, null, ''),
security: sc_revoke_refund_nonce
};
wc_sc_meta_boxes_order_items.block();
$.ajax({
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
type: 'POST',
data: data,
success: function (response) {
if (true === response.success) {
// Redirect to same page for show the refunded status
window.location.reload();
} else {
console.log(response.data.error);
}
}
});
}
})
});
</script>
<?php
$order = wc_get_order( $order_id );
$order_items = ( is_object( $order ) && is_callable( array( $order, 'get_items' ) ) ) ? $order->get_items( 'coupon' ) : array();
$tax_data = ( function_exists( 'wc_tax_enabled' ) && wc_tax_enabled() && is_object( $order ) && is_callable( array( $order, 'get_taxes' ) ) ) ? $order->get_taxes() : array();
if ( ! empty( $order_items ) ) {
$item_titles = array_map(
function( $item ) {
return $item->get_name();
},
$order_items
);
$posts = $this->get_post_by_title( $item_titles, OBJECT, 'shop_coupon' );
foreach ( $order_items as $item_id => $item ) {
$sc_refunded_discount = $sc_refunded_discount_tax = $sc_refunded_user = $sc_refunded_timestamp = 0; // phpcs:ignore
$coupon_code = ( $this->is_callable( $item, 'get_name' ) ) ? $item->get_name() : '';
$sanitized_coupon_code = sanitize_title( $coupon_code ); // The generated string will be checked in an array key to locate post object.
$coupon_post_obj = ( ! empty( $posts[ $sanitized_coupon_code ] ) ) ? $posts[ $sanitized_coupon_code ] : null;
$coupon_id = isset( $coupon_post_obj->ID ) ? $coupon_post_obj->ID : '';
$coupon_title = isset( $coupon_post_obj->post_title ) ? $coupon_post_obj->post_title : '';
$coupon = new WC_Coupon( $coupon_id );
if ( is_callable( array( $this, 'get_order_item_meta' ) ) ) {
$sc_refunded_discount = (float) $this->get_order_item_meta( $item_id, 'sc_refunded_discount', true );
$sc_refunded_discount_tax = (float) $this->get_order_item_meta( $item_id, 'sc_refunded_discount_tax', true );
$sc_refunded_user = $this->get_order_item_meta( $item_id, 'sc_refunded_user_id', true );
$sc_refunded_timestamp = $this->get_order_item_meta( $item_id, 'sc_refunded_timestamp', true );
}
if ( empty( $sc_refunded_timestamp ) ) {
$sc_refunded_timestamp = time() + $this->wc_timezone_offset();
}
$sc_refunded_discount = empty( $sc_refunded_discount ) ? 0 : $sc_refunded_discount;
$sc_refunded_discount_tax = empty( $sc_refunded_discount_tax ) ? 0 : $sc_refunded_discount_tax;
if ( is_a( $coupon, 'WC_Coupon' ) ) {
if ( $coupon->is_type( 'smart_coupon' ) && ( ! empty( $sc_refunded_discount ) || ! empty( $sc_refunded_discount_tax ) ) ) {
$who_refunded = new WP_User( $sc_refunded_user );
$refunder_id = isset( $who_refunded->ID ) ? $who_refunded->ID : 0;
$refunder_name = isset( $who_refunded->display_name ) ? $who_refunded->display_name : '';
?>
<input type="hidden" name="sc_revoke_refund_nonce" id="sc_revoke_refund_nonce" value="<?php echo esc_attr( wp_create_nonce( 'sc_revoke_refund_nonce' ) ); ?>">
<tr class="refund wc_sc_refunded" data-wc_sc_refunded_id="<?php echo esc_attr( $item_id ); ?>"
data-wc_sc_coupon_id="<?php echo esc_attr( $coupon_id ); ?>"
data-wc_sc_order_id="<?php echo esc_attr( $order_id ); ?>"
data-wc_sc_refunded_amount_tax="<?php echo esc_attr( $sc_refunded_discount_tax ); ?>"
data-wc_sc_refunded_amount="<?php echo esc_attr( $sc_refunded_discount ); ?>">
<td class="thumb">
<div></div>
</td>
<td class="name">
<?php
if ( $who_refunded->exists() ) {
printf(
/* translators: 1: refund id 2: refund date 3: username */
esc_html__( 'Refund %1$s - %2$s by %3$s', 'woocommerce-smart-coupons' ),
sprintf( '%s - %s', ( ! empty( $store_credit_label['singular'] ) ? esc_html( $store_credit_label['singular'] ) : esc_html__( 'Store Credit', 'woocommerce-smart-coupons' ) ), esc_html( $coupon_title ) ),
esc_html( $this->format_date( $sc_refunded_timestamp ) ),
sprintf(
'<abbr class="refund_by" title="%1$s">%2$s</abbr>',
/* translators: 1: ID who refunded */
sprintf( esc_attr__( 'ID: %d', 'woocommerce-smart-coupons' ), absint( $refunder_id ) ),
esc_html( $refunder_name )
)
);
} else {
printf(
/* translators: 1: refund id 2: refund date */
esc_html__( 'Refund %1$s - %2$s', 'woocommerce-smart-coupons' ),
sprintf( '%s - %s', ( ! empty( $store_credit_label['singular'] ) ? esc_html( $store_credit_label['singular'] ) : esc_html__( 'Store Credit', 'woocommerce-smart-coupons' ) ), esc_html( $coupon_title ) ),
esc_html( $this->format_date( $sc_refunded_timestamp ) )
);
}
?>
</td>
<td class="item_cost" width="1%">&nbsp;</td>
<td class="quantity" width="1%">&nbsp;</td>
<td class="line_cost" width="1%">
<div class="view">
<?php
$total = $sc_refunded_discount + $sc_refunded_discount_tax;
echo wp_kses_post(
wc_price( '-' . $total )
);
?>
</div>
</td>
<?php if ( ! empty( $tax_data ) ) : ?>
<td class="line_tax" width="1%"></td>
<?php
$tax_data_count = count( $tax_data );
if ( $tax_data_count > 1 ) {
?>
<td colspan="<?php echo esc_attr( $tax_data_count - 1 ); ?>"></td>
<?php } ?>
<?php endif; ?>
<td class="wc-order-edit-line-item">
<div class="wc-order-edit-line-item-actions">
<a class="delete_wc_sc_refund" href="#" style=""></a>
</div>
</td>
</tr>
<?php
}
}
}
}
}
/**
* Formatting the date
*
* @param timestamp $date timestamp for date.
* @param string $format date format.
* @return string date format string
*/
protected function format_date( $date, $format = '' ) {
if ( ! is_int( $date ) ) {
$date = intval( $date );
}
if ( empty( $format ) ) {
$format = get_option( 'date_format', 'F j, Y' ) . ' ' . get_option( 'time_format', 'g:i a' );
}
return gmdate( $format, $date );
}
/**
* Revoke refund store credit
*
* @return void remove refund store credit amount to the coupon
*/
public function wc_sc_revoke_refunded_store_credit() {
$nonce_token = ! empty( $_POST['security'] ) ? $_POST['security'] : ''; // phpcs:ignore
if ( wp_verify_nonce( wp_unslash( $nonce_token ), 'sc_revoke_refund_nonce' ) ) {
$line_item = ! empty( $_POST['line_items'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['line_items'] ) ), true ) : array();
if ( ! empty( $line_item ) ) {
$smart_coupon_id = ! empty( $line_item['coupon_id'] ) ? $line_item['coupon_id'] : 0;
$refunded_amount = ! empty( $line_item['refund_amount'] ) ? $line_item['refund_amount'] : 0;
$refunded_amount_tax = ! empty( $line_item['refund_amount_tax'] ) ? $line_item['refund_amount_tax'] : 0;
$wc_sc_refunded_id = ! empty( $line_item['wc_sc_refunded_id'] ) ? $line_item['wc_sc_refunded_id'] : 0;
$order_id = ! empty( $line_item['wc_sc_order_id'] ) ? $line_item['wc_sc_order_id'] : 0;
$order = ( ! is_a( $order, 'WC_Order' ) ) ? wc_get_order( $order_id ) : $order;
$order_discount_amount = $this->get_order_item_meta( $wc_sc_refunded_id, 'discount_amount', true );
$order_discount_tax_amount = $this->get_order_item_meta( $wc_sc_refunded_id, 'discount_amount_tax', true );
if ( $order_discount_amount >= $refunded_amount && $order_discount_tax_amount >= $refunded_amount_tax && ! empty( $smart_coupon_id ) ) {
$coupon = new WC_Coupon( $smart_coupon_id );
if ( is_a( $coupon, 'WC_Coupon' ) ) {
if ( $this->is_wc_gte_30() ) {
$discount_type = ( is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
} else {
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
}
$coupon_amount = $this->get_amount( $coupon, true, $order );
if ( 'smart_coupon' === $discount_type ) {
if ( ! is_numeric( $refunded_amount ) ) {
$refunded_amount = 0;
}
if ( ! is_numeric( $refunded_amount_tax ) ) {
$refunded_amount_tax = 0;
}
$refund_amount = $refunded_amount + $refunded_amount_tax;
$amount = $coupon_amount - $refund_amount;
$this->update_post_meta( $smart_coupon_id, 'coupon_amount', $amount, true, $order );
$user = ( function_exists( 'get_current_user_id' ) ) ? get_current_user_id() : 0;
$local_time = ( function_exists( 'current_datetime' ) ) ? current_datetime() : '';
$get_timestamp = ( is_object( $local_time ) && is_callable( array( $local_time, 'getTimestamp' ) ) ) ? $local_time->getTimestamp() : 0;
$get_offset = ( is_object( $local_time ) && is_callable( array( $local_time, 'getOffset' ) ) ) ? $local_time->getOffset() : 0;
$current_time_stamp = $get_timestamp + $get_offset;
if ( is_callable( array( $this, 'update_order_item_meta' ) ) ) {
$this->update_order_item_meta( $wc_sc_refunded_id, 'sc_revoke_refunded_discount', $refunded_amount, true );
$this->update_order_item_meta( $wc_sc_refunded_id, 'sc_revoke_refunded_discount_tax', $refunded_amount_tax, true );
$this->update_order_item_meta( $wc_sc_refunded_id, 'sc_revoke_refunded_user_id', $user );
$this->update_order_item_meta( $wc_sc_refunded_id, 'sc_revoke_refunded_timestamp', $current_time_stamp );
$this->update_order_item_meta( $wc_sc_refunded_id, 'sc_revoke_refunded_coupon_id', $smart_coupon_id );
$this->update_order_item_meta( $wc_sc_refunded_id, 'sc_refunded_discount', 0 );
$this->update_order_item_meta( $wc_sc_refunded_id, 'sc_refunded_discount_tax', 0 );
}
}
}
}
}
wp_send_json_success();
} else {
wp_send_json_error();
}
}
/**
* Change order status when fully refunded.
*
* @param string $status order status.
* @param number $order_id order id.
* @param number $refund_id refund id.
* @return false|mixed order status
*/
public function update_fully_refunded_status( $status, $order_id, $refund_id ) {
$order = wc_get_order( $order_id );
$order_items = ( is_object( $order ) && is_callable( array( $order, 'get_items' ) ) ) ? $order->get_items( 'coupon' ) : array();
if ( ! empty( $order_items ) ) {
$item_titles = array_map(
function( $item ) {
return $item->get_name();
},
$order_items
);
$posts = $this->get_post_by_title( $item_titles, OBJECT, 'shop_coupon' );
foreach ( $order_items as $item_id => $item ) {
$sc_refunded_discount = $sc_refunded_discount_tax = $order_discount_amount = $order_discount_tax_amount = 0; // phpcs:ignore
$coupon_code = ( $this->is_callable( $item, 'get_name' ) ) ? $item->get_name() : '';
$sanitized_coupon_code = sanitize_title( $coupon_code ); // The generated string will be checked in an array key to locate post object.
$coupon_post_obj = ( ! empty( $posts[ $sanitized_coupon_code ] ) ) ? $posts[ $sanitized_coupon_code ] : null;
$coupon_id = isset( $coupon_post_obj->ID ) ? $coupon_post_obj->ID : '';
$coupon = new WC_Coupon( $coupon_id );
if ( is_callable( array( $this, 'get_order_item_meta' ) ) ) {
$sc_refunded_discount = $this->get_order_item_meta( $item_id, 'sc_refunded_discount', true );
$sc_refunded_discount_tax = $this->get_order_item_meta( $item_id, 'sc_refunded_discount_tax', true );
$order_discount_amount = $this->get_order_item_meta( $item_id, 'discount_amount', true );
$order_discount_tax_amount = $this->get_order_item_meta( $item_id, 'discount_amount_tax', true );
}
if ( is_a( $coupon, 'WC_Coupon' ) ) {
if ( $coupon->is_type( 'smart_coupon' ) ) {
$get_order_total = ( is_object( $order ) && is_callable( array( $order, 'get_total' ) ) ) ? $order->get_total() : 0;
$refunded_order_total = ( is_object( $order ) && is_callable( array( $order, 'get_total_refunded' ) ) ) ? $order->get_total_refunded() : 0;
if ( empty( $get_order_total ) && empty( $sc_refunded_discount_tax ) && empty( $order_discount_tax_amount ) && $order_discount_amount !== $sc_refunded_discount ) {
return false;
} elseif ( empty( $get_order_total ) && ! empty( $sc_refunded_discount_tax ) && ! empty( $order_discount_tax_amount ) && $order_discount_amount !== $sc_refunded_discount && $sc_refunded_discount_tax !== $order_discount_tax_amount ) {
return false;
} elseif ( ! empty( $get_order_total ) && empty( $sc_refunded_discount_tax ) && empty( $order_discount_tax_amount ) && $get_order_total === $refunded_order_total && $order_discount_amount !== $sc_refunded_discount ) {
return false;
} elseif ( ! empty( $get_order_total ) && ! empty( $sc_refunded_discount_tax ) && ! empty( $order_discount_tax_amount ) && $get_order_total === $refunded_order_total && $order_discount_amount !== $sc_refunded_discount && $sc_refunded_discount_tax !== $order_discount_tax_amount ) {
return false;
} elseif ( empty( $sc_refunded_discount_tax ) && ! empty( $order_discount_tax_amount ) ) {
return false;
}
}
}
}
}
return $status;
}
}
}
WC_SC_Coupon_Refund_Process::get_instance();

View File

@@ -0,0 +1,573 @@
<?php
/**
* Class to handle feature Coupons By Excluded Email
*
* @author StoreApps
* @category Admin
* @package wocommerce-smart-coupons/includes
* @since 6.7.0
* @version 1.6.1
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupons_By_Excluded_Email' ) ) {
/**
* Class WC_SC_Coupons_By_Excluded_Email
*/
class WC_SC_Coupons_By_Excluded_Email {
/**
* Variable to hold instance of this class
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'wc_sc_start_coupon_options_email_restriction', array( $this, 'usage_restriction' ) );
add_action( 'woocommerce_coupon_options_save', array( $this, 'process_meta' ), 10, 2 );
add_filter( 'woocommerce_coupon_is_valid', array( $this, 'validate' ), 11, 3 );
add_action( 'woocommerce_after_checkout_validation', array( $this, 'check_customer_coupons' ), 99, 2 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'wc_sc_process_coupon_meta_value_for_import', array( $this, 'import_coupon_meta' ), 10, 2 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_meta' ) );
add_filter( 'manage_shop_coupon_posts_columns', array( $this, 'define_columns' ), 12 );
add_action( 'manage_shop_coupon_posts_custom_column', array( $this, 'render_columns' ), 10, 2 );
}
/**
* Get single instance of this class
*
* @return this class Singleton object of this class
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name = '', $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Display field for coupon by excluded email
*
* @param array $args Arguments.
*/
public function usage_restriction( $args = array() ) {
$coupon_id = ( ! empty( $args['coupon_id'] ) ) ? absint( $args['coupon_id'] ) : 0;
$coupon = ( ! empty( $args['coupon_obj'] ) ) ? $args['coupon_obj'] : null;
$excluded_emails = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_meta' ) ) ) ? $coupon->get_meta( 'wc_sc_excluded_customer_email' ) : get_post_meta( $coupon_id, 'wc_sc_excluded_customer_email', true );
if ( ! is_array( $excluded_emails ) || empty( $excluded_emails ) ) {
$excluded_emails = array();
}
woocommerce_wp_text_input(
array(
'id' => 'wc_sc_excluded_customer_email',
'label' => __( 'Excluded emails', 'woocommerce-smart-coupons' ),
'placeholder' => __( 'No restrictions', 'woocommerce-smart-coupons' ),
'description' => __( 'List of excluded billing emails to check against when an order is placed. Separate email addresses with commas. You can also use an asterisk (*) to match parts of an email. For example "*@gmail.com" would match all gmail addresses.', 'woocommerce-smart-coupons' ),
'value' => implode( ', ', $excluded_emails ),
'desc_tip' => true,
'type' => 'email',
'class' => '',
'custom_attributes' => array(
'multiple' => 'multiple',
),
)
);
}
/**
* Save coupon by excluded email data in meta
*
* @param Integer $post_id The coupon post ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function process_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$excluded_emails = ( isset( $_POST['wc_sc_excluded_customer_email'] ) ) ? wc_clean( wp_unslash( $_POST['wc_sc_excluded_customer_email'] ) ) : ''; // phpcs:ignore
$excluded_emails = explode( ',', $excluded_emails );
$excluded_emails = array_map( 'trim', $excluded_emails );
$excluded_emails = array_filter( $excluded_emails, 'is_email' );
$excluded_emails = array_filter( $excluded_emails );
if ( $this->is_callable( $coupon, 'update_meta_data' ) && $this->is_callable( $coupon, 'save' ) ) {
$coupon->update_meta_data( 'wc_sc_excluded_customer_email', $excluded_emails );
$coupon->save();
} else {
update_post_meta( $post_id, 'wc_sc_excluded_customer_email', $excluded_emails );
}
}
/**
* Validate the coupon based on user role
*
* @param boolean $valid Is valid or not.
* @param WC_Coupon $coupon The coupon object.
* @param WC_Discounts $discounts The discount object.
*
* @throws Exception If the coupon is invalid.
* @return boolean Is valid or not
*/
public function validate( $valid = false, $coupon = object, $discounts = null ) {
// If coupon is invalid already, no need for further checks.
if ( false === $valid ) {
return $valid;
}
$post_action = ( ! empty( $_POST['action'] ) ) ? wc_clean( wp_unslash( $_POST['action'] ) ) : ''; // phpcs:ignore
if ( is_admin() && wp_doing_ajax() && 'woocommerce_add_coupon_discount' === $post_action ) { // This condition will allow the addition of coupon from admin side, in the order even if the user role is not matching.
return true;
}
$is_auto_applied = did_action( 'wc_sc_before_auto_apply_coupons' ) > 0;
$cart = ( function_exists( 'WC' ) && isset( WC()->cart ) ) ? WC()->cart : null;
$coupon_id = ( $this->is_wc_gte_30() ) ? $coupon->get_id() : $coupon->id;
if ( ! is_a( $coupon, 'WC_Coupon' ) ) {
$coupon = new WC_Coupon( $coupon_id );
}
if ( $this->is_callable( $coupon, 'get_meta' ) ) {
$coupon_code = ( $this->is_callable( $coupon, 'get_code' ) ) ? $coupon->get_code() : '';
$customer_email = ( $this->is_callable( $coupon, 'get_email_restrictions' ) ) ? $coupon->get_email_restrictions() : array();
$exclude_customer_email = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_sc_excluded_customer_email' ) : array();
} else {
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
$customer_email = get_post_meta( $coupon_id, 'customer_email', true );
$exclude_customer_email = get_post_meta( $coupon_id, 'wc_sc_excluded_customer_email', true );
}
$wc_customer = WC()->customer;
$wc_customer_email = ( $this->is_callable( $wc_customer, 'get_email' ) ) ? $wc_customer->get_email() : '';
$wc_customer_billing_email = ( $this->is_callable( $wc_customer, 'get_billing_email' ) ) ? $wc_customer->get_billing_email() : '';
$current_user = ( is_user_logged_in() ) ? wp_get_current_user() : null;
$user_email = ( ! is_null( $current_user ) && ! empty( $current_user->user_email ) ) ? $current_user->user_email : '';
$billing_email = ( ! empty( $_REQUEST['billing_email'] ) ) ? wc_clean( wp_unslash( $_REQUEST['billing_email'] ) ) : ''; // phpcs:ignore
$check_emails = array_unique(
array_filter(
array_map(
'strtolower',
array_map(
'sanitize_email',
array(
$billing_email,
$wc_customer_billing_email,
$wc_customer_email,
$user_email,
)
)
)
)
);
if ( false === $is_auto_applied && empty( $check_emails ) ) {
return $valid;
}
$is_callable_coupon_emails_allowed = $this->is_callable( $cart, 'is_coupon_emails_allowed' );
$is_validate_allowed_emails = apply_filters(
'wc_sc_force_validate_allowed_emails',
true,
array(
'source' => $this,
'is_valid' => $valid,
'coupon_obj' => $coupon,
'discounts_obj' => $discounts,
)
);
if ( true === $is_validate_allowed_emails && is_array( $customer_email ) && 0 < count( $customer_email ) && true === $is_callable_coupon_emails_allowed && ! $cart->is_coupon_emails_allowed( $check_emails, $customer_email ) ) {
if ( true === $is_auto_applied ) {
$valid = false;
if ( $this->is_callable( $cart, 'has_discount' ) && $cart->has_discount( $coupon_code ) && $this->is_callable( $cart, 'remove_coupon' ) ) {
if ( class_exists( 'WC_Coupon' ) && $this->is_callable( $coupon, 'add_coupon_message' ) ) {
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED );
}
$cart->remove_coupon( $coupon_code );
}
} else {
throw new Exception( __( 'This coupon is not valid for you.', 'woocommerce-smart-coupons' ) );
}
}
if ( is_array( $exclude_customer_email ) && 0 < count( $exclude_customer_email ) && true === $is_callable_coupon_emails_allowed && $cart->is_coupon_emails_allowed( $check_emails, $exclude_customer_email ) ) {
if ( true === $is_auto_applied ) {
$valid = false;
if ( $this->is_callable( $cart, 'has_discount' ) && $cart->has_discount( $coupon_code ) && $this->is_callable( $cart, 'remove_coupon' ) ) {
if ( class_exists( 'WC_Coupon' ) && $this->is_callable( $coupon, 'add_coupon_message' ) ) {
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED );
}
$cart->remove_coupon( $coupon_code );
}
} else {
throw new Exception( __( 'This coupon is not valid for you.', 'woocommerce-smart-coupons' ) );
}
}
return $valid;
}
/**
* Now that we have billing email, check if the coupon is excluded to be used for the user or billing email
*
* Credit: WooCommerce
*
* @param array $posted Post data.
*/
public function check_customer_coupons( $posted = array() ) {
$cart = ( function_exists( 'WC' ) && isset( WC()->cart ) ) ? WC()->cart : null;
if ( is_a( $cart, 'WC_Cart' ) ) {
$is_cart_empty = is_callable( array( $cart, 'is_empty' ) ) && $cart->is_empty();
if ( false === $is_cart_empty ) {
$applied_coupons = ( is_callable( array( $cart, 'get_applied_coupons' ) ) ) ? $cart->get_applied_coupons() : array();
if ( ! empty( $applied_coupons ) ) {
foreach ( $applied_coupons as $code ) {
$coupon = new WC_Coupon( $code );
if ( $this->is_valid( $coupon ) ) {
// Get user and posted emails to compare.
$current_user = ( is_user_logged_in() ) ? wp_get_current_user() : null;
$user_email = ( ! is_null( $current_user ) && ! empty( $current_user->user_email ) ) ? $current_user->user_email : '';
$billing_email = isset( $posted['billing_email'] ) ? $posted['billing_email'] : '';
$check_emails = array_unique(
array_filter(
array_map(
'strtolower',
array_map(
'sanitize_email',
array(
$billing_email,
$user_email,
)
)
)
)
);
if ( is_object( $coupon ) && is_callable( array( $coupon, 'get_meta' ) ) ) {
$exclude_restrictions = $coupon->get_meta( 'wc_sc_excluded_customer_email' );
} else {
if ( is_object( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) {
$coupon_id = $coupon->get_id();
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
}
$exclude_restrictions = ( ! empty( $coupon_id ) ) ? get_post_meta( $coupon_id, 'wc_sc_excluded_customer_email', true ) : array();
}
if ( is_array( $exclude_restrictions ) && 0 < count( $exclude_restrictions ) && is_callable( array( $coupon, 'add_coupon_message' ) ) && is_callable( array( $cart, 'remove_coupon' ) ) && is_callable( array( $cart, 'is_coupon_emails_allowed' ) ) && $cart->is_coupon_emails_allowed( $check_emails, $exclude_restrictions ) ) {
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED );
$cart->remove_coupon( $code );
}
/*
|===========================================================================================================================================================================|
| |
| Before this method, WooCommerce checks for Allowed emails. |
| And in that method, it already checks for the usage limit whether it is allowed to apply the coupon or not. |
| 1. If it's allowed, it means the usage limit is within reach & we can proceed with checking for excluded email. |
| Because the main purpose of excluded email is to prevent application of coupon. And since the usage limit is already checked, it's not needed to check it again |
| 2. If it's not allowed, the process will not reach in this method, as it's already invalidated. |
| |
|===========================================================================================================================================================================|
*/
}
}
}
}
}
}
/**
* Add meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$headers['wc_sc_excluded_customer_email'] = __( 'Excluded emails', 'woocommerce-smart-coupons' );
return $headers;
}
/**
* Post meta defaults for excluded email ids meta
*
* @param array $defaults Existing postmeta defaults.
* @return array $defaults Modified postmeta defaults
*/
public function postmeta_defaults( $defaults = array() ) {
$defaults['wc_sc_excluded_customer_email'] = '';
return $defaults;
}
/**
* Make meta data of excluded email ids protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected = false, $meta_key = '', $meta_type = '' ) {
$sc_excluded_email_keys = array(
'wc_sc_excluded_customer_email',
);
if ( in_array( $meta_key, $sc_excluded_email_keys, true ) ) {
return true;
}
return $protected;
}
/**
* Add excluded email in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array Modified data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
$excluded_emails = ( isset( $post['wc_sc_excluded_customer_email'] ) ) ? wc_clean( wp_unslash( $post['wc_sc_excluded_customer_email'] ) ) : ''; // phpcs:ignore
$excluded_emails = explode( ',', $excluded_emails );
$excluded_emails = array_map( 'trim', $excluded_emails );
$excluded_emails = array_filter( $excluded_emails, 'is_email' );
$excluded_emails = array_filter( $excluded_emails );
$excluded_emails = implode( ',', $excluded_emails );
$data['wc_sc_excluded_customer_email'] = $excluded_emails;
return $data;
}
/**
* Process coupon meta value for import
*
* @param mixed $meta_value The meta value.
* @param array $args Additional Arguments.
* @return mixed $meta_value
*/
public function import_coupon_meta( $meta_value = null, $args = array() ) {
if ( ! empty( $args['meta_key'] ) && 'wc_sc_excluded_customer_email' === $args['meta_key'] ) {
$excluded_emails = ( isset( $args['postmeta']['wc_sc_excluded_customer_email'] ) ) ? wc_clean( wp_unslash( $args['postmeta']['wc_sc_excluded_customer_email'] ) ) : ''; // phpcs:ignore
$excluded_emails = explode( ',', $excluded_emails );
$excluded_emails = array_map( 'trim', $excluded_emails );
$excluded_emails = array_filter( $excluded_emails, 'is_email' );
$meta_value = array_filter( $excluded_emails );
}
return $meta_value;
}
/**
* Function to copy excluded email meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_meta( $args = array() ) {
$new_coupon_id = ( ! empty( $args['new_coupon_id'] ) ) ? absint( $args['new_coupon_id'] ) : 0;
$coupon = ( ! empty( $args['ref_coupon'] ) ) ? $args['ref_coupon'] : false;
if ( empty( $new_coupon_id ) || empty( $coupon ) ) {
return;
}
if ( $this->is_wc_gte_30() && is_object( $coupon ) && is_callable( array( $coupon, 'get_meta' ) ) ) {
$excluded_emails = $coupon->get_meta( 'wc_sc_excluded_customer_email' );
} else {
$old_coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$excluded_emails = get_post_meta( $old_coupon_id, 'wc_sc_excluded_customer_email', true );
}
if ( ! is_array( $excluded_emails ) || empty( $excluded_emails ) ) {
$excluded_emails = array();
}
$new_coupon = new WC_Coupon( $new_coupon_id );
if ( is_object( $new_coupon ) && is_callable( array( $new_coupon, 'update_meta_data' ) ) && is_callable( array( $new_coupon, 'save' ) ) ) {
$new_coupon->update_meta_data( 'wc_sc_excluded_customer_email', $excluded_emails );
$new_coupon->save();
} else {
update_post_meta( $new_coupon_id, 'wc_sc_excluded_customer_email', $excluded_emails );
}
}
/**
* Define which columns to show on this screen.
*
* @param array $columns Existing columns.
* @return array
*/
public function define_columns( $columns = array() ) {
if ( ! is_array( $columns ) || empty( $columns ) ) {
$columns = array();
}
$columns['wc_sc_coupon_allowed_emails'] = __( 'Allowed emails', 'woocommerce-smart-coupons' );
$columns['wc_sc_coupon_excluded_emails'] = __( 'Excluded emails', 'woocommerce-smart-coupons' );
return $columns;
}
/**
* Render individual columns.
*
* @param string $column Column ID to render.
* @param int $post_id Post ID being shown.
*/
public function render_columns( $column = '', $post_id = 0 ) {
if ( empty( $post_id ) || empty( $column ) || ! in_array( $column, array( 'wc_sc_coupon_allowed_emails', 'wc_sc_coupon_excluded_emails' ), true ) ) {
return;
}
$coupon = new WC_Coupon( $post_id );
switch ( $column ) {
case 'wc_sc_coupon_allowed_emails':
$this->render_allowed_emails_column( $post_id, $coupon );
break;
case 'wc_sc_coupon_excluded_emails':
$this->render_excluded_emails_column( $post_id, $coupon );
break;
}
}
/**
* Function to render allowed emails column on coupons dashboard.
*
* @param int $post_id The coupon ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function render_allowed_emails_column( $post_id = 0, $coupon = null ) {
$emails = ( $this->is_callable( $coupon, 'get_email_restrictions' ) ) ? $coupon->get_email_restrictions() : $this->get_post_meta( $post_id, 'customer_email', true );
echo wp_kses_post(
$this->email_column_value(
$emails,
array(
'coupon_id' => $post_id,
'coupon_obj' => $coupon,
'filter' => true, // Allow filtering coupon list by selected "allowed email".
)
)
);
}
/**
* Function to render excluded emails column on coupons dashboard.
*
* @param int $post_id The coupon ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function render_excluded_emails_column( $post_id = 0, $coupon = null ) {
$emails = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_sc_excluded_customer_email' ) : $this->get_post_meta( $post_id, 'wc_sc_excluded_customer_email', true );
echo wp_kses_post(
$this->email_column_value(
$emails,
array(
'coupon_id' => $post_id,
'coupon_obj' => $coupon,
)
)
);
}
/**
* Get value for email columns.
*
* @param array $emails The list of email addresses.
* @param array $args Additional arguments.
* @return string $value
*/
public function email_column_value( $emails = array(), $args = array() ) {
$coupon_id = ( ! empty( $args['coupon_id'] ) ) ? absint( $args['coupon_id'] ) : 0;
$coupon = ( ! empty( $args['coupon_obj'] ) ) ? $args['coupon_obj'] : null;
$filter = ( ! empty( $args['filter'] ) ) ? $args['filter'] : false;
$value = '<span class="na">&ndash;</span>';
if ( ! empty( $emails ) ) {
$email_count = apply_filters(
'wc_sc_email_column_max_count',
$this->sc_get_option( 'wc_sc_email_column_max_count', 5 ),
array(
'source' => $this,
'coupon_id' => $coupon_id,
'coupon_obj' => $coupon,
'filter' => $filter,
)
);
$visible_emails = ( ! empty( $email_count ) && is_array( $emails ) ) ? array_slice( $emails, 0, $email_count ) : array();
if ( ! empty( $visible_emails ) ) {
$mapped_emails = ( true === $filter ) ? array_map( array( $this, 'filter_by_email_link' ), $visible_emails ) : $visible_emails;
$value = implode( ', ', $mapped_emails );
}
}
return $value;
}
}
}
WC_SC_Coupons_By_Excluded_Email::get_instance();

View File

@@ -0,0 +1,710 @@
<?php
/**
* Class to handle feature Coupons By Location
*
* @author StoreApps
* @category Admin
* @package wocommerce-smart-coupons/includes
* @version 1.9.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupons_By_Location' ) ) {
/**
* Class WC_SC_Coupons_By_Location
*/
class WC_SC_Coupons_By_Location {
/**
* Variable to hold instance of this class
*
* @var $instance
*/
private static $instance = null;
/**
* Additional Locations
*
* @var $additional_locations
*/
public $additional_locations = array();
/**
* Countries
*
* @var $countries
*/
public $countries;
/**
* Global Additional Locations
*
* @var $global_additional_locations
*/
public $global_additional_locations = array();
/**
* Custom Locations
*
* @var $custom_locations
*/
public $custom_locations = array();
/**
* Locations Lookup In
*
* @var $locations_lookup_in
*/
public $locations_lookup_in;
/**
* Address
*
* @var $address
*/
public $address;
/**
* Constructor
*/
private function __construct() {
add_action( 'init', array( $this, 'initialize_cbl_additional_locations' ) );
add_filter( 'woocommerce_coupon_is_valid', array( $this, 'validate' ), 11, 3 );
if ( is_admin() ) {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_javascript_css' ) );
add_action( 'woocommerce_coupon_options_usage_restriction', array( $this, 'usage_restriction' ) );
add_action( 'woocommerce_coupon_options_save', array( $this, 'process_meta' ), 10, 2 );
}
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'wc_sc_export_coupon_meta_data', array( $this, 'export_coupon_meta_data' ), 10, 2 );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_filter( 'wc_sc_process_coupon_meta_value_for_import', array( $this, 'process_coupon_meta_value_for_import' ), 10, 2 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_action_meta' ) );
}
/**
* Get single instance of this class
*
* @return this class Singleton object of this class
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Initialize additional locations
*/
public function initialize_cbl_additional_locations() {
if ( empty( $this->global_additional_locations ) ) {
$this->global_additional_locations = get_option( 'sa_cbl_additional_locations', array() );
}
}
/**
* Styles & scripts
*/
public function enqueue_admin_javascript_css() {
global $woocommerce_smart_coupon;
$post_type = $this->get_post_type();
$get_page = ( ! empty( $_GET['page'] ) ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
if ( 'shop_coupon' !== $post_type && 'wc-smart-coupons' !== $get_page ) {
return;
}
$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
// Add customized chosen javascript library for adding new location from same field.
wp_register_script( 'sa_coupons_by_location_chosen', plugins_url( '/', dirname( __FILE__ ) ) . 'assets/js/chosen.jquery' . $suffix . '.js', array( 'jquery' ), $woocommerce_smart_coupon->plugin_data['Version'], true );
wp_enqueue_style( 'sa_coupons_by_location_css', plugins_url( '/', dirname( __FILE__ ) ) . 'assets/css/cbl-admin' . $suffix . '.css', array(), $woocommerce_smart_coupon->plugin_data['Version'] );
}
/**
* Display field for coupon by location
*/
public function usage_restriction() {
global $post;
if ( ! wp_script_is( 'sa_coupons_by_location_chosen' ) ) {
wp_enqueue_script( 'sa_coupons_by_location_chosen' );
}
$coupon = ( ! empty( $post->ID ) ) ? new WC_Coupon( $post->ID ) : null;
$is_callable_coupon_get_meta = $this->is_callable( $coupon, 'get_meta' );
$this->locations_lookup_in = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'sa_cbl_locations_lookup_in' ) : get_post_meta( $post->ID, 'sa_cbl_locations_lookup_in', true );
if ( ! is_array( $this->locations_lookup_in ) || empty( $this->locations_lookup_in ) ) {
$this->locations_lookup_in = array( 'address' => 'billing' );
$this->update_post_meta( $post->ID, 'sa_cbl_locations_lookup_in', $this->locations_lookup_in );
}
$this->address = $this->locations_lookup_in['address'];
$is_wc_countries = function_exists( 'WC' ) && is_object( WC()->countries );
$continents = ( $is_wc_countries && $this->is_callable( WC()->countries, 'get_continents' ) ) ? WC()->countries->get_continents() : array();
$countries = ( $is_wc_countries && $this->is_callable( WC()->countries, 'get_countries' ) ) ? WC()->countries->get_countries() : array();
$all_states = ( $is_wc_countries && $this->is_callable( WC()->countries, 'get_states' ) ) ? WC()->countries->get_states() : array();
?>
<div class="options_group smart-coupons-field" id="locations">
<p class="form-field">
<span class='search_in'><label><?php echo esc_html__( 'Address to look in', 'woocommerce-smart-coupons' ); ?></label></span>
<label for="billing" class="billing">
<input type="radio" name="sa_cbl_search_in[address]" value="billing" <?php ( ! empty( $this->address ) && 'billing' === $this->address ) ? checked( $this->address, 'billing' ) : ''; ?> />
<?php echo esc_html__( 'Billing', 'woocommerce-smart-coupons' ); ?>
</label> &nbsp;
<label for="shipping" class="shipping">
<input type="radio" name="sa_cbl_search_in[address]" value="shipping" <?php ( ! empty( $this->address ) && 'shipping' === $this->address ) ? checked( $this->address, 'shipping' ) : ''; ?> />
<?php echo esc_html__( 'Shipping', 'woocommerce-smart-coupons' ); ?>
</label>
</p>
<p class="form-field">
<label class="options_header"><?php echo esc_html__( 'Locations', 'woocommerce-smart-coupons' ); ?></label>
<?php
$locations = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'sa_cbl_' . $this->address . '_locations' ) : get_post_meta( $post->ID, 'sa_cbl_' . $this->address . '_locations', true );
if ( empty( $locations ) || ! is_array( $locations ) ) {
$locations = array();
}
if ( ! array_key_exists( 'additional_locations', $locations ) || ! is_array( $locations['additional_locations'] ) ) {
$locations['additional_locations'] = array();
}
$this->additional_locations = array_map( 'html_entity_decode', $locations['additional_locations'] );
$this->countries = WC()->countries->countries;
echo '<select name="locations[additional_locations][]" id="cc_list" data-placeholder="' . esc_html__( 'Select location', 'woocommerce-smart-coupons' ) . '..." class="sa_cbl_search_location sa_cbl_add_location" multiple>';
if ( ! empty( $continents ) ) {
foreach ( $continents as $continent_code => $continent ) {
?>
<optgroup label="<?php echo esc_attr( ( ! empty( $continent['name'] ) ) ? $continent['name'] : $continent_code ); ?>">
<?php
if ( ! empty( $continent['countries'] ) ) {
foreach ( $continent['countries'] as $country_code ) {
if ( array_key_exists( $country_code, $countries ) && ! empty( $countries[ $country_code ] ) ) {
?>
<option value="<?php echo esc_attr( $country_code ); ?>"
<?php
if ( ! empty( $this->additional_locations ) ) {
$encoding = $this->mb_detect_encoding( $country_code, 'UTF-8, ISO-8859-1', true );
$decoded_country_code = ( false !== $encoding ) ? html_entity_decode( $country_code, ENT_COMPAT, $encoding ) : $country_code;
echo esc_attr( selected( in_array( $decoded_country_code, $this->additional_locations, true ) ) );
}
?>
><?php echo esc_html( ( ! empty( $countries[ $country_code ] ) ) ? trim( $countries[ $country_code ] ) : trim( $country_code ) ); ?>
</option>
<?php
}
}
}
?>
</optgroup>
<?php
}
}
if ( ! empty( $all_states ) ) {
foreach ( $all_states as $country_code => $states ) {
if ( empty( $states ) ) {
continue;
}
?>
<optgroup label="<?php echo esc_attr( ( ! empty( $countries[ $country_code ] ) ) ? $countries[ $country_code ] : $country_code ); ?>">
<?php
if ( ! empty( $states ) ) {
foreach ( $states as $state_code => $state_name ) {
$country_state_code = $country_code . '::' . $state_code;
?>
<option value="<?php echo esc_attr( $country_state_code ); ?>"
<?php
if ( ! empty( $this->additional_locations ) ) {
$encoding = $this->mb_detect_encoding( $country_state_code, 'UTF-8, ISO-8859-1', true );
$decoded_country_state_code = ( false !== $encoding ) ? html_entity_decode( $country_state_code, ENT_COMPAT, $encoding ) : $country_state_code;
echo esc_attr( selected( in_array( $decoded_country_state_code, $this->additional_locations, true ) ) );
}
?>
><?php echo esc_html( trim( $state_name ) ); ?>
</option>
<?php
}
}
?>
</optgroup>
<?php
}
}
// others.
echo ' <optgroup label="' . esc_html__( 'Select Additional Locations', 'woocommerce-smart-coupons' ) . '"> ';
if ( ! empty( $this->global_additional_locations ) ) {
foreach ( $this->global_additional_locations as $list ) {
echo '<option value="' . esc_attr( $list ) . '"';
if ( ! empty( $this->additional_locations ) ) {
$encoding = $this->mb_detect_encoding( $list, 'UTF-8, ISO-8859-1', true );
$decoded_list = ( false !== $encoding ) ? html_entity_decode( $list, ENT_COMPAT, $encoding ) : $list;
echo esc_attr( selected( in_array( $decoded_list, $this->additional_locations, true ) ) );
}
echo '>' . esc_html( ucwords( strtolower( $list ) ) ) . '</option>';
}
}
echo ' </optgroup> ';
echo '</select>';
?>
</p>
</div>
<?php
$js = "jQuery('select.sa_cbl_search_location').chosen({
disable_search_threshold: 10,
width: '50%',
no_results_text: '" . __( 'Entered location not found. On pressing "Enter" button, a new custom location will be saved as: ', 'woocommerce-smart-coupons' ) . "'
});";
$js .= "jQuery('#cc_list_chosen').on('click', function(){
var cc_height = jQuery('#cc_list_chosen').height();
jQuery('#cc_list_chosen .chosen-drop').attr('style', 'bottom: '+cc_height+'px !important; border-bottom: 0 !important; border-top: 1px solid #aaa !important; top: auto !important;');
});
";
wc_enqueue_js( $js );
}
/**
* Save coupon by location data in meta
*
* @param Integer $post_id The coupon post ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function process_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$locations = ( ! empty( $_POST['locations'] ) ) ? wc_clean( wp_unslash( $_POST['locations'] ) ) : array(); // phpcs:ignore
$this->locations_lookup_in['address'] = ( ! empty( $_POST['sa_cbl_search_in']['address'] ) ) ? wc_clean( wp_unslash( $_POST['sa_cbl_search_in']['address'] ) ) : ''; // phpcs:ignore
if ( $this->is_callable( $coupon, 'update_meta_data' ) && $this->is_callable( $coupon, 'save' ) ) {
$coupon->update_meta_data( 'sa_cbl_' . $this->locations_lookup_in['address'] . '_locations', $locations );
if ( isset( $this->locations_lookup_in['address'] ) && ! empty( $this->locations_lookup_in['address'] ) ) {
$coupon->update_meta_data( 'sa_cbl_locations_lookup_in', $this->locations_lookup_in );
}
$coupon->save();
} else {
update_post_meta( $post_id, 'sa_cbl_' . $this->locations_lookup_in['address'] . '_locations', $locations );
if ( isset( $this->locations_lookup_in['address'] ) && ! empty( $this->locations_lookup_in['address'] ) ) {
update_post_meta( $post_id, 'sa_cbl_locations_lookup_in', $this->locations_lookup_in );
}
}
$this->countries = array_map( 'strtolower', WC()->countries->countries );
if ( ! empty( $locations['additional_locations'] ) ) {
$this->additional_locations = array_map( 'strtolower', $locations['additional_locations'] );
}
if ( count( $this->additional_locations ) > 0 ) {
// Loop through all location entered in Billing location of coupons.
// and collect those location which is not available in WooCommerce countries.
foreach ( $this->additional_locations as $location ) {
if ( ! in_array( $location, $this->countries, true ) ) {
$this->custom_locations[] = strtolower( $location );
}
}
// Add new location with already saved locations.
if ( false !== $this->global_additional_locations && ! empty( $this->global_additional_locations ) ) {
$this->global_additional_locations = array_merge( $this->global_additional_locations, $this->custom_locations );
} else {
$this->global_additional_locations = $this->custom_locations;
}
// Discard duplicate values, arrange alphabetically & save.
$this->global_additional_locations = array_unique( $this->global_additional_locations );
sort( $this->global_additional_locations );
update_option( 'sa_cbl_additional_locations', $this->global_additional_locations, 'no' );
}
}
/**
* Validate the coupon based on location
*
* @param boolean $valid Is valid or not.
* @param WC_Coupon $coupon The coupon object.
* @param WC_Discounts $discounts The discount object.
*
* @throws Exception If the coupon is invalid.
* @return boolean Is valid or not
*/
public function validate( $valid, $coupon, $discounts = null ) {
global $checkout;
// If coupon is invalid already, no need for further checks.
if ( ! $valid ) {
return $valid;
}
$coupon_id = ( $this->is_wc_gte_30() ) ? $coupon->get_id() : $coupon->id;
$is_callable_coupon_get_meta = $this->is_callable( $coupon, 'get_meta' );
$this->locations_lookup_in = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'sa_cbl_locations_lookup_in' ) : get_post_meta( $coupon_id, 'sa_cbl_locations_lookup_in', true );
if ( empty( $this->locations_lookup_in ) || empty( $this->locations_lookup_in['address'] ) ) {
return $valid;
}
$locations = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'sa_cbl_' . $this->locations_lookup_in['address'] . '_locations' ) : get_post_meta( $coupon_id, 'sa_cbl_' . $this->locations_lookup_in['address'] . '_locations', true );
if ( ! empty( $locations ) && is_array( $locations ) && ! empty( $locations['additional_locations'] ) && is_array( $locations['additional_locations'] ) && array_key_exists( 'additional_locations', $locations ) ) {
$wc_customer = WC()->customer;
$wc_countries = WC()->countries;
$check_live_details = false;
$wc_ajax_action = ( ! empty( $_REQUEST['wc-ajax'] ) ) ? wc_clean( wp_unslash( $_REQUEST['wc-ajax'] ) ) : ''; // phpcs:ignore
if ( defined( 'WC_DOING_AJAX' ) && WC_DOING_AJAX && 'update_order_review' === $wc_ajax_action ) {
check_ajax_referer( 'update-order-review', 'security' );
$check_live_details = true;
}
// Collect country, state & city.
if ( 'billing' === $this->locations_lookup_in['address'] ) {
if ( $this->is_wc_gte_30() ) {
$customer_billing_country = ( true === $check_live_details && ! empty( $_REQUEST['country'] ) ) ? wc_clean( wp_unslash( $_REQUEST['country'] ) ) : $wc_customer->get_billing_country(); // phpcs:ignore
$customer_billing_state = ( true === $check_live_details && ! empty( $_REQUEST['state'] ) ) ? wc_clean( wp_unslash( $_REQUEST['state'] ) ) : $wc_customer->get_billing_state(); // phpcs:ignore
$customer_billing_city = ( true === $check_live_details && ! empty( $_REQUEST['city'] ) ) ? wc_clean( wp_unslash( $_REQUEST['city'] ) ) : $wc_customer->get_billing_city(); // phpcs:ignore
$customer_billing_postcode = ( true === $check_live_details && ! empty( $_REQUEST['postcode'] ) ) ? wc_clean( wp_unslash( $_REQUEST['postcode'] ) ) : $wc_customer->get_billing_postcode(); // phpcs:ignore
$current_country = ( ! empty( $customer_billing_country ) ) ? $customer_billing_country : '';
$current_state = ( ! empty( $customer_billing_state ) ) ? $customer_billing_state : '';
$current_city = ( ! empty( $customer_billing_city ) ) ? $customer_billing_city : '';
$current_post_code = ( ! empty( $customer_billing_postcode ) ) ? $customer_billing_postcode : '';
} else {
$current_country = ( ! empty( $wc_customer->country ) ) ? $wc_customer->country : '';
$current_state = ( ! empty( $wc_customer->state ) ) ? $wc_customer->state : '';
$current_city = ( ! empty( $wc_customer->city ) ) ? $wc_customer->city : '';
$current_post_code = ( ! empty( $wc_customer->postcode ) ) ? $wc_customer->postcode : '';
}
} else {
if ( $this->is_wc_gte_30() ) {
$customer_shipping_country = ( true === $check_live_details && ! empty( $_REQUEST['s_country'] ) ) ? wc_clean( wp_unslash( $_REQUEST['s_country'] ) ) : $wc_customer->get_shipping_country(); // phpcs:ignore
$customer_shipping_state = ( true === $check_live_details && ! empty( $_REQUEST['s_state'] ) ) ? wc_clean( wp_unslash( $_REQUEST['s_state'] ) ) : $wc_customer->get_shipping_state(); // phpcs:ignore
$customer_shipping_city = ( true === $check_live_details && ! empty( $_REQUEST['s_city'] ) ) ? wc_clean( wp_unslash( $_REQUEST['s_city'] ) ) : $wc_customer->get_shipping_city(); // phpcs:ignore
$customer_shipping_postcode = ( true === $check_live_details && ! empty( $_REQUEST['s_postcode'] ) ) ? wc_clean( wp_unslash( $_REQUEST['s_postcode'] ) ) : $wc_customer->get_shipping_postcode(); // phpcs:ignore
$current_country = ( ! empty( $customer_shipping_country ) ) ? $customer_shipping_country : '';
$current_state = ( ! empty( $customer_shipping_state ) ) ? $customer_shipping_state : '';
$current_city = ( ! empty( $customer_shipping_city ) ) ? $customer_shipping_city : '';
$current_post_code = ( ! empty( $customer_shipping_postcode ) ) ? $customer_shipping_postcode : '';
} else {
$current_country = ( ! empty( $wc_customer->shipping_country ) ) ? $wc_customer->shipping_country : '';
$current_state = ( ! empty( $wc_customer->shipping_state ) ) ? $wc_customer->shipping_state : '';
$current_city = ( ! empty( $wc_customer->shipping_city ) ) ? $wc_customer->shipping_city : '';
$current_post_code = ( ! empty( $wc_customer->shipping_postcode ) ) ? $wc_customer->shipping_postcode : '';
}
}
// Convert country code or state code to actual country & state.
$country = ( ! empty( $wc_countries->countries[ $current_country ] ) ) ? strtolower( $wc_countries->countries[ $current_country ] ) : '';
$state = ( ! empty( $wc_countries->states[ $current_country ][ $current_state ] ) ) ? strtolower( $wc_countries->states[ $current_country ][ $current_state ] ) : strtolower( $current_state );
$city = ( ! empty( $current_city ) ) ? strtolower( $current_city ) : '';
$post_code = ( ! empty( $current_post_code ) ) ? strtolower( $current_post_code ) : '';
// Loop through additional_locations and return true on matching with either country, state or city.
// Return false otherwise.
foreach ( $locations['additional_locations'] as $additional_location ) {
if ( false !== strpos( $additional_location, '::' ) ) {
$exploded_location = explode( '::', $additional_location );
$additional_location_country = ( ! empty( $exploded_location[0] ) ) ? $exploded_location[0] : '';
$additional_location_state = ( ! empty( $exploded_location[1] ) ) ? $exploded_location[1] : '';
if ( $current_country === $additional_location_country && $current_state === $additional_location_state ) {
return true;
}
}
if ( $current_country === $additional_location || $current_state === $additional_location || $country === $additional_location || $state === $additional_location || $city === $additional_location || $post_code === $additional_location ) {
return true;
}
}
throw new Exception( __( 'Coupon is not valid for the', 'woocommerce-smart-coupons' ) . ' ' . ( ( 'billing' === $this->locations_lookup_in['address'] ) ? __( 'billing address', 'woocommerce-smart-coupons' ) : __( 'shipping address', 'woocommerce-smart-coupons' ) ) );
}
return $valid;
}
/**
* Add meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$cbl_headers = array(
'sa_cbl_locations_lookup_in' => __( 'Locations lookup in', 'woocommerce-smart-coupons' ),
'sa_cbl_billing_locations' => __( 'Billing Locations', 'woocommerce-smart-coupons' ),
'sa_cbl_shipping_locations' => __( 'Shipping Locations', 'woocommerce-smart-coupons' ),
);
return array_merge( $headers, $cbl_headers );
}
/**
* Function to handle coupon meta data during export of existing coupons
*
* @param mixed $meta_value The meta value.
* @param array $args Additional arguments.
* @return string Processed meta value
*/
public function export_coupon_meta_data( $meta_value = '', $args = array() ) {
if ( ! empty( $args['meta_key'] ) && in_array( $args['meta_key'], array( 'sa_cbl_billing_locations', 'sa_cbl_shipping_locations' ), true ) ) {
switch ( $args['meta_key'] ) {
case 'sa_cbl_billing_locations':
case 'sa_cbl_shipping_locations':
$meta_value = ( ! empty( $meta_value['additional_locations'] ) ) ? implode( '|', wc_clean( wp_unslash( $meta_value['additional_locations'] ) ) ) : '';
break;
}
}
return $meta_value;
}
/**
* Post meta defaults for CBL's meta
*
* @param array $defaults Existing postmeta defaults.
* @return array
*/
public function postmeta_defaults( $defaults = array() ) {
$cbl_defaults = array(
'sa_cbl_locations_lookup_in' => '',
'sa_cbl_billing_locations' => '',
'sa_cbl_shipping_locations' => '',
);
return array_merge( $defaults, $cbl_defaults );
}
/**
* Add CBL's meta with value in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array Modified data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
$data['sa_cbl_locations_lookup_in'] = ( ! empty( $post['sa_cbl_search_in']['address'] ) ) ? wc_clean( wp_unslash( $post['sa_cbl_search_in']['address'] ) ) : '';
$data['sa_cbl_billing_locations'] = ( ! empty( $data['sa_cbl_locations_lookup_in'] ) && 'billing' === $data['sa_cbl_locations_lookup_in'] && ! empty( $post['locations']['additional_locations'] ) && is_array( $post['locations']['additional_locations'] ) ) ? implode( '|', wc_clean( wp_unslash( $post['locations']['additional_locations'] ) ) ) : '';
$data['sa_cbl_shipping_locations'] = ( ! empty( $data['sa_cbl_locations_lookup_in'] ) && 'shipping' === $data['sa_cbl_locations_lookup_in'] && ! empty( $post['locations']['additional_locations'] ) && is_array( $post['locations']['additional_locations'] ) ) ? implode( '|', wc_clean( wp_unslash( $post['locations']['additional_locations'] ) ) ) : '';
if ( ! empty( $post['locations']['additional_locations'] ) ) {
$additional_locations = wc_clean( wp_unslash( $post['locations']['additional_locations'] ) );
$this->update_global_additional_locations( $additional_locations );
}
return $data;
}
/**
* Make meta data of SC CBL, protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected, $meta_key, $meta_type ) {
$sc_meta = array(
'sa_cbl_locations_lookup_in' => '',
'sa_cbl_billing_locations' => '',
'sa_cbl_shipping_locations' => '',
);
if ( in_array( $meta_key, $sc_meta, true ) ) {
return true;
}
return $protected;
}
/**
* Function to copy CBL meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_action_meta( $args = array() ) {
$new_coupon_id = ( ! empty( $args['new_coupon_id'] ) ) ? absint( $args['new_coupon_id'] ) : 0;
$coupon = ( ! empty( $args['ref_coupon'] ) ) ? $args['ref_coupon'] : false;
if ( empty( $new_coupon_id ) || empty( $coupon ) ) {
return;
}
if ( $this->is_wc_gte_30() ) {
$locations_lookup_in = $coupon->get_meta( 'sa_cbl_locations_lookup_in' );
$billing_locations = $coupon->get_meta( 'sa_cbl_billing_locations' );
$shipping_locations = $coupon->get_meta( 'sa_cbl_shipping_locations' );
} else {
$old_coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$locations_lookup_in = get_post_meta( $old_coupon_id, 'sa_cbl_locations_lookup_in', true );
$billing_locations = get_post_meta( $old_coupon_id, 'sa_cbl_billing_locations', true );
$shipping_locations = get_post_meta( $old_coupon_id, 'sa_cbl_shipping_locations', true );
}
$new_coupon = new WC_Coupon( $new_coupon_id );
if ( $this->is_callable( $new_coupon, 'update_meta_data' ) && $this->is_callable( $new_coupon, 'save' ) ) {
$new_coupon->update_meta_data( 'sa_cbl_locations_lookup_in', $locations_lookup_in );
$new_coupon->update_meta_data( 'sa_cbl_billing_locations', $billing_locations );
$new_coupon->update_meta_data( 'sa_cbl_shipping_locations', $shipping_locations );
$new_coupon->save();
} else {
update_post_meta( $new_coupon_id, 'sa_cbl_locations_lookup_in', $locations_lookup_in );
update_post_meta( $new_coupon_id, 'sa_cbl_billing_locations', $billing_locations );
update_post_meta( $new_coupon_id, 'sa_cbl_shipping_locations', $shipping_locations );
}
if ( ! empty( $billing_locations['additional_locations'] ) ) {
$this->update_global_additional_locations( $billing_locations['additional_locations'] );
}
if ( ! empty( $shipping_locations['additional_locations'] ) ) {
$this->update_global_additional_locations( $shipping_locations['additional_locations'] );
}
}
/**
* Process coupon meta value for import
*
* @param mixed $meta_value The meta value.
* @param array $args Additional Arguments.
* @return mixed $meta_value
*/
public function process_coupon_meta_value_for_import( $meta_value = null, $args = array() ) {
if ( ! empty( $args['meta_key'] ) && in_array( $args['meta_key'], array( 'sa_cbl_locations_lookup_in', 'sa_cbl_billing_locations', 'sa_cbl_shipping_locations' ), true ) ) {
switch ( $args['meta_key'] ) {
case 'sa_cbl_locations_lookup_in':
$meta_value = ( ! empty( $args['postmeta']['sa_cbl_locations_lookup_in'] ) ) ? array( 'address' => wc_clean( wp_unslash( $args['postmeta']['sa_cbl_locations_lookup_in'] ) ) ) : array();
break;
case 'sa_cbl_billing_locations':
$meta_value = ( ! empty( $args['postmeta']['sa_cbl_billing_locations'] ) ) ? array( 'additional_locations' => explode( '|', wc_clean( wp_unslash( $args['postmeta']['sa_cbl_billing_locations'] ) ) ) ) : array();
break;
case 'sa_cbl_shipping_locations':
$meta_value = ( ! empty( $args['postmeta']['sa_cbl_shipping_locations'] ) ) ? array( 'additional_locations' => explode( '|', wc_clean( wp_unslash( $args['postmeta']['sa_cbl_shipping_locations'] ) ) ) ) : array();
break;
}
if ( in_array( $args['meta_key'], array( 'sa_cbl_billing_locations', 'sa_cbl_shipping_locations' ), true ) && ! empty( $meta_value['additional_locations'] ) ) {
$this->update_global_additional_locations( $meta_value['additional_locations'] );
}
}
return $meta_value;
}
/**
* Update global additional locations
*
* @param array $additional_locations The locations.
*/
public function update_global_additional_locations( $additional_locations = array() ) {
if ( empty( $additional_locations ) ) {
return;
}
$additional_locations = array_map( 'strtolower', $additional_locations );
$wc_countries = array_map( 'strtolower', WC()->countries->countries );
foreach ( $wc_countries as $index => $country ) {
$encoding = $this->mb_detect_encoding( $country, 'UTF-8, ISO-8859-1', true );
$wc_countries[ $index ] = ( false !== $encoding ) ? html_entity_decode( $country, ENT_COMPAT, $encoding ) : $country;
}
if ( count( $additional_locations ) > 0 ) {
$custom_locations = array();
// Loop through all location entered in Billing location of coupons.
// and collect those location which is not available in WooCommerce countries.
foreach ( $additional_locations as $location ) {
if ( ! in_array( $location, $wc_countries, true ) ) {
$custom_locations[] = $location;
}
}
$global_additional_locations = ( ! empty( $this->global_additional_locations ) ) ? $this->global_additional_locations : get_option( 'sa_cbl_additional_locations', array() );
// Add new location with already saved locations.
if ( false !== $global_additional_locations && ! empty( $global_additional_locations ) ) {
$global_additional_locations = array_merge( $global_additional_locations, $custom_locations );
} else {
$global_additional_locations = $custom_locations;
}
// Discard duplicate values, arrange alphabetically & save.
$global_additional_locations = array_unique( $global_additional_locations );
sort( $global_additional_locations );
update_option( 'sa_cbl_additional_locations', $global_additional_locations, 'no' );
}
}
}
}
WC_SC_Coupons_By_Location::get_instance();

View File

@@ -0,0 +1,420 @@
<?php
/**
* Class to handle feature Coupons By Payment Method
*
* @author StoreApps
* @category Admin
* @package wocommerce-smart-coupons/includes
* @version 1.7.1
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupons_By_Payment_Method' ) ) {
/**
* Class WC_SC_Coupons_By_Payment_Method
*/
class WC_SC_Coupons_By_Payment_Method {
/**
* Variable to hold instance of this class
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_coupon_options_usage_restriction', array( $this, 'usage_restriction' ), 10, 2 );
add_action( 'woocommerce_coupon_options_save', array( $this, 'process_meta' ), 10, 2 );
add_filter( 'woocommerce_coupon_is_valid', array( $this, 'validate' ), 11, 3 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'wc_sc_export_coupon_meta', array( $this, 'export_coupon_meta_data' ), 10, 2 );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'wc_sc_process_coupon_meta_value_for_import', array( $this, 'process_coupon_meta_value_for_import' ), 10, 2 );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_payment_method_meta' ) );
add_action( 'wp_footer', array( $this, 'styles_and_scripts' ) );
}
/**
* Get single instance of this class
*
* @return this class Singleton object of this class
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name = '', $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Display field for coupon by payment method
*
* @param integer $coupon_id The coupon id.
* @param WC_Coupon $coupon The coupon object.
*/
public function usage_restriction( $coupon_id = 0, $coupon = null ) {
$payment_method_ids = array();
if ( ! empty( $coupon_id ) ) {
$payment_method_ids = $this->get_post_meta( $coupon_id, 'wc_sc_payment_method_ids', true );
if ( empty( $payment_method_ids ) || ! is_array( $payment_method_ids ) ) {
$payment_method_ids = array();
}
}
$available_payment_methods = WC()->payment_gateways->get_available_payment_gateways();
?>
<div class="options_group smart-coupons-field">
<p class="form-field">
<label for="wc_sc_payment_method_ids"><?php echo esc_html__( 'Payment methods', 'woocommerce-smart-coupons' ); ?></label>
<select id="wc_sc_payment_method_ids" name="wc_sc_payment_method_ids[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No payment methods', 'woocommerce-smart-coupons' ); ?>">
<?php
if ( is_array( $available_payment_methods ) && ! empty( $available_payment_methods ) ) {
foreach ( $available_payment_methods as $payment_method ) {
echo '<option value="' . esc_attr( $payment_method->id ) . '"' . esc_attr( selected( in_array( $payment_method->id, $payment_method_ids, true ), true, false ) ) . '>' . esc_html( $payment_method->get_title() ) . '</option>';
}
}
?>
</select>
<?php
$tooltip_text = esc_html__( 'Payment methods that must be selected during checkout for this coupon to be valid.', 'woocommerce-smart-coupons' );
echo wc_help_tip( $tooltip_text ); // phpcs:ignore
?>
</p>
</div>
<?php
}
/**
* Save coupon by payment method data in meta
*
* @param Integer $post_id The coupon post ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function process_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$payment_method_ids = ( isset( $_POST['wc_sc_payment_method_ids'] ) ) ? wc_clean( wp_unslash( $_POST['wc_sc_payment_method_ids'] ) ) : array(); // phpcs:ignore
if ( $this->is_callable( $coupon, 'update_meta_data' ) && $this->is_callable( $coupon, 'save' ) ) {
$coupon->update_meta_data( 'wc_sc_payment_method_ids', $payment_method_ids );
$coupon->save();
} else {
$this->update_post_meta( $post_id, 'wc_sc_payment_method_ids', $payment_method_ids );
}
}
/**
* Validate the coupon based on payment method
*
* @param boolean $valid Is valid or not.
* @param WC_Coupon $coupon The coupon object.
* @param WC_Discounts $discounts The discount object.
*
* @throws Exception If the coupon is invalid.
* @return boolean Is valid or not
*/
public function validate( $valid = false, $coupon = object, $discounts = object ) {
// If coupon is already invalid, no need for further checks.
if ( false === $valid ) {
return $valid;
}
if ( ! $coupon instanceof WC_Coupon ) {
return $valid;
}
if ( ! $discounts instanceof WC_Discounts ) {
return $valid;
}
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
$coupon_code = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
if ( empty( $coupon_id ) ) {
return $valid;
}
$payment_method_ids = $this->get_post_meta( $coupon_id, 'wc_sc_payment_method_ids', true );
$cart_or_order_object = is_callable( array( $discounts, 'get_object' ) ) ? $discounts->get_object() : null;
$is_wc_session = is_a( $cart_or_order_object, 'WC_Cart' ) && function_exists( 'WC' ) && isset( WC()->session ) && is_object( WC()->session );
$needs_payment = ( $this->is_callable( $cart_or_order_object, 'needs_payment' ) ) ? $cart_or_order_object->needs_payment() : true;
$posted_data = array();
$post_data = isset( $_POST['post_data'] ) && ! empty( $_POST['post_data'] ) ? wc_clean( wp_unslash( $_POST['post_data'] ) ) : ''; // phpcs:ignore
wp_parse_str( $post_data, $posted_data );
if ( true === $needs_payment && is_array( $payment_method_ids ) && ! empty( $payment_method_ids ) ) {
$payment_titles = $this->get_payment_method_titles_by_ids( $payment_method_ids );
$chosen_payment_method = '';
if ( is_a( $cart_or_order_object, 'WC_Order' ) ) {
$chosen_payment_method = is_callable( array( $cart_or_order_object, 'get_payment_method' ) ) ? $cart_or_order_object->get_payment_method() : '';
} elseif ( ! empty( $posted_data ) && isset( $posted_data['payment_method'] ) ) {
$chosen_payment_method = $posted_data['payment_method'];
} elseif ( true === $is_wc_session ) {
$chosen_payment_method = ( WC()->session->__isset( 'chosen_payment_method' ) ) ? WC()->session->get( 'chosen_payment_method' ) : '';
}
if ( ! in_array( $chosen_payment_method, $payment_method_ids, true ) ) {
if ( true === $is_wc_session && is_callable( array( WC()->session, 'set' ) ) ) {
WC()->session->set( 'wc_sc_reload_payment_method', 'yes' );
}
$applied_coupons = ( WC()->cart instanceof WC_Cart && is_callable( array( WC()->cart, 'get_applied_coupons' ) ) ) ? WC()->cart->get_applied_coupons() : array();
if ( ! empty( $applied_coupons ) && in_array( $coupon_code, $applied_coupons, true ) ) {
WC()->cart->remove_coupon( $coupon_code );
/* translators: 1. The coupon code 2. The text 'payment method/s' 3. List of payment method names 4. Link to the checkout page */
wc_add_notice( sprintf( __( 'Coupon code %1$s has been removed. It is valid only for %2$s: %3$s. You can change the payment method from the %4$s page.', 'woocommerce-smart-coupons' ), '<code>' . $coupon_code . '</code>', _n( 'payment method', 'payment methods', count( $payment_titles ), 'woocommerce-smart-coupons' ), '<strong>"' . implode( '", "', $payment_titles ) . '"</strong>', '<a href="' . esc_url( wc_get_checkout_url() ) . '"><strong>' . __( 'Checkout', 'woocommerce-smart-coupons' ) . '</strong></a>' ), 'error' );
}
/* translators: 1. The coupon code 2. The text 'payment method/s' 3. List of payment method names 4. Link to the checkout page */
throw new Exception( sprintf( __( 'Coupon code %1$s is valid only for %2$s: %3$s. You can change payment method from the %4$s page.', 'woocommerce-smart-coupons' ), '<code>' . $coupon_code . '</code>', _n( 'payment method', 'payment methods', count( $payment_titles ), 'woocommerce-smart-coupons' ), '<strong>"' . implode( '", "', $payment_titles ) . '"</strong>', '<a href="' . esc_url( wc_get_checkout_url() ) . '"><strong>' . __( 'Checkout', 'woocommerce-smart-coupons' ) . '</strong></a>' ) );
}
if ( true === $is_wc_session && is_callable( array( WC()->session, 'set' ) ) ) {
WC()->session->set( 'wc_sc_reload_payment_method', 'no' );
}
}
return $valid;
}
/**
* Add meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$headers['wc_sc_payment_method_ids'] = __( 'Payment methods', 'woocommerce-smart-coupons' );
return $headers;
}
/**
* Function to handle coupon meta data during export of existing coupons
*
* @param mixed $meta_value The meta value.
* @param array $args Additional arguments.
* @return string Processed meta value
*/
public function export_coupon_meta_data( $meta_value = '', $args = array() ) {
if ( ! empty( $args['meta_key'] ) && 'wc_sc_payment_method_ids' === $args['meta_key'] ) {
if ( isset( $args['meta_value'] ) && ! empty( $args['meta_value'] ) ) {
$payment_method_ids = maybe_unserialize( stripslashes( $args['meta_value'] ) );
if ( is_array( $payment_method_ids ) && ! empty( $payment_method_ids ) ) {
$payment_method_titles = $this->get_payment_method_titles_by_ids( $payment_method_ids );
if ( is_array( $payment_method_titles ) && ! empty( $payment_method_titles ) ) {
$meta_value = implode( '|', wc_clean( wp_unslash( $payment_method_titles ) ) ); // Replace payment method ids with their respective method titles.
}
}
}
}
return $meta_value;
}
/**
* Post meta defaults for payment method ids meta
*
* @param array $defaults Existing postmeta defaults.
* @return array $defaults Modified postmeta defaults
*/
public function postmeta_defaults( $defaults = array() ) {
$defaults['wc_sc_payment_method_ids'] = '';
return $defaults;
}
/**
* Add payment method's meta with value in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array $data Modified row data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
$payment_method_titles = '';
if ( ! empty( $post['wc_sc_payment_method_ids'] ) && is_array( $post['wc_sc_payment_method_ids'] ) ) {
$payment_method_titles = $this->get_payment_method_titles_by_ids( $post['wc_sc_payment_method_ids'] );
if ( is_array( $payment_method_titles ) && ! empty( $payment_method_titles ) ) {
$payment_method_titles = implode( '|', wc_clean( wp_unslash( $payment_method_titles ) ) );
}
}
$data['wc_sc_payment_method_ids'] = $payment_method_titles; // Replace payment method ids with their respective method titles.
return $data;
}
/**
* Function to get payment method titles for given payment method ids
*
* @param array $payment_method_ids ids of payment methods.
* @return array $payment_method_titles titles of payment methods
*/
public function get_payment_method_titles_by_ids( $payment_method_ids = array() ) {
$payment_method_titles = array();
if ( is_array( $payment_method_ids ) && ! empty( $payment_method_ids ) ) {
$available_payment_methods = WC()->payment_gateways->get_available_payment_gateways();
foreach ( $payment_method_ids as $index => $payment_method_id ) {
$payment_method = ( isset( $available_payment_methods[ $payment_method_id ] ) && ! empty( $available_payment_methods[ $payment_method_id ] ) ) ? $available_payment_methods[ $payment_method_id ] : '';
if ( ! empty( $payment_method ) && is_a( $payment_method, 'WC_Payment_Gateway' ) ) {
$payment_method_title = is_callable( array( $payment_method, 'get_title' ) ) ? $payment_method->get_title() : '';
if ( ! empty( $payment_method_title ) ) {
$payment_method_titles[ $index ] = $payment_method_title; // Replace payment method id with it's repective title.
} else {
$payment_method_titles[ $index ] = $payment_method->id; // In case of empty payment method title replace it with method id.
}
}
}
}
return $payment_method_titles;
}
/**
* Process coupon meta value for import
*
* @param mixed $meta_value The meta value.
* @param array $args Additional Arguments.
* @return mixed $meta_value
*/
public function process_coupon_meta_value_for_import( $meta_value = null, $args = array() ) {
if ( ! empty( $args['meta_key'] ) && 'wc_sc_payment_method_ids' === $args['meta_key'] ) {
$meta_value = ( ! empty( $args['postmeta']['wc_sc_payment_method_ids'] ) ) ? explode( '|', wc_clean( wp_unslash( $args['postmeta']['wc_sc_payment_method_ids'] ) ) ) : array();
if ( is_array( $meta_value ) && ! empty( $meta_value ) ) {
$available_payment_methods = WC()->payment_gateways->get_available_payment_gateways();
if ( is_array( $available_payment_methods ) && ! empty( $available_payment_methods ) ) {
foreach ( $meta_value as $index => $payment_method_title ) {
foreach ( $available_payment_methods as $payment_method ) {
$method_title = is_callable( array( $payment_method, 'get_title' ) ) ? $payment_method->get_title() : '';
if ( $method_title === $payment_method_title && ! empty( $payment_method->id ) ) {
$meta_value[ $index ] = $payment_method->id; // Replace payment method title with it's respective id.
}
}
}
}
}
}
return $meta_value;
}
/**
* Function to copy payment method restriction meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_payment_method_meta( $args = array() ) {
// Copy meta data to new coupon.
$this->copy_coupon_meta_data(
$args,
array( 'wc_sc_payment_method_ids' )
);
}
/**
* Make meta data of payment method ids protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected = false, $meta_key = '', $meta_type = '' ) {
if ( 'wc_sc_payment_method_ids' === $meta_key ) {
return true;
}
return $protected;
}
/**
* Function to add styles & scripts
*/
public function styles_and_scripts() {
if ( is_woocommerce() || is_cart() || is_checkout() || is_product_category() || is_product_tag() || is_account_page() ) {
$js = "
try {
let checkoutForm = document.querySelector('form.checkout');
if( checkoutForm ){
checkoutForm.addEventListener('change', function(event) {
if (event.target && event.target.name === 'payment_method') {
setTimeout(function() {
document.body.dispatchEvent(new Event('update_checkout'));
}, 1000);
}
});
}
} catch( error ) {
console.error( '" . __( 'An error occurred:', 'woocommerce-smart-coupons' ) . "', error);
}";
wc_enqueue_js( $js );
}
}
}
}
WC_SC_Coupons_By_Payment_Method::get_instance();

View File

@@ -0,0 +1,644 @@
<?php
/**
* Class to handle feature Coupons By Product Attribute
*
* @author StoreApps
* @category Admin
* @package wocommerce-smart-coupons/includes
* @version 1.8.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupons_By_Product_Attribute' ) ) {
/**
* Class WC_SC_Coupons_By_Product_Attribute
*/
class WC_SC_Coupons_By_Product_Attribute {
/**
* Variable to hold instance of this class
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_coupon_options_usage_restriction', array( $this, 'usage_restriction' ), 10, 2 );
add_action( 'woocommerce_coupon_options_save', array( $this, 'process_meta' ), 10, 2 );
add_filter( 'woocommerce_coupon_is_valid_for_product', array( $this, 'validate' ), 11, 4 );
add_filter( 'woocommerce_coupon_is_valid', array( $this, 'handle_non_product_type_coupons' ), 11, 3 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_attribute_meta' ), 10, 2 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_attributes_meta' ) );
}
/**
* Get single instance of this class
*
* @return this class Singleton object of this class
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name = '', $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Display field for coupon by product attribute
*
* @param integer $coupon_id The coupon id.
* @param WC_Coupon $coupon The coupon object.
*/
public function usage_restriction( $coupon_id = 0, $coupon = null ) {
global $wp_version;
$product_attribute_ids = array();
$exclude_product_attribute_ids = array();
$coupon_types = wc_get_coupon_types();
$product_coupon_types = wc_get_product_coupon_types();
$non_product_coupon_types = array();
foreach ( $coupon_types as $coupon_type => $coupon_label ) {
if ( ! in_array( $coupon_type, $product_coupon_types, true ) ) {
$non_product_coupon_types[] = $coupon_label;
}
}
if ( ! empty( $non_product_coupon_types ) ) {
$non_product_coupon_types_label = '"' . implode( ', ', $non_product_coupon_types ) . '"';
} else {
$non_product_coupon_types_label = '';
}
if ( ! empty( $coupon_id ) ) {
$coupon = ( ! empty( $coupon_id ) ) ? new WC_Coupon( $coupon_id ) : null;
$is_callable_coupon_get_meta = $this->is_callable( $coupon, 'get_meta' );
$product_attribute_ids = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'wc_sc_product_attribute_ids' ) : get_post_meta( $coupon_id, 'wc_sc_product_attribute_ids', true );
if ( ! empty( $product_attribute_ids ) ) {
$product_attribute_ids = explode( '|', $product_attribute_ids );
} else {
$product_attribute_ids = array();
}
$exclude_product_attribute_ids = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'wc_sc_exclude_product_attribute_ids' ) : get_post_meta( $coupon_id, 'wc_sc_exclude_product_attribute_ids', true );
if ( ! empty( $exclude_product_attribute_ids ) ) {
$exclude_product_attribute_ids = explode( '|', $exclude_product_attribute_ids );
} else {
$exclude_product_attribute_ids = array();
}
}
$attribute_taxonomies = wc_get_attribute_taxonomies();
$attribute_options = array();
$attribute_taxonomies_label = array();
if ( ! empty( $attribute_taxonomies ) && is_array( $attribute_taxonomies ) ) {
$attribute_taxonomies_name = array();
foreach ( $attribute_taxonomies as $attribute_taxonomy ) {
$attribute_name = isset( $attribute_taxonomy->attribute_name ) ? $attribute_taxonomy->attribute_name : '';
$attribute_label = isset( $attribute_taxonomy->attribute_label ) ? $attribute_taxonomy->attribute_label : '';
if ( ! empty( $attribute_name ) && ! empty( $attribute_label ) ) {
$attribute_taxonomy_name = wc_attribute_taxonomy_name( $attribute_name );
$attribute_taxonomies_name[] = $attribute_taxonomy_name;
$attribute_taxonomies_label[ $attribute_taxonomy_name ] = $attribute_label;
}
}
if ( ! empty( $attribute_taxonomies_name ) ) {
$args = array(
'orderby' => 'name',
'hide_empty' => 0,
);
$args = apply_filters( 'woocommerce_product_attribute_terms', $args );
if ( version_compare( $wp_version, '4.5.0', '>=' ) ) {
$attribute_taxonomies_terms = get_terms(
array_merge(
array(
'taxonomy' => $attribute_taxonomies_name,
),
$args
)
);
} else {
$attribute_taxonomies_terms = get_terms( $attribute_taxonomies_name, $args );
}
if ( ! empty( $attribute_taxonomies_terms ) && is_array( $attribute_taxonomies_terms ) ) {
foreach ( $attribute_taxonomies_terms as $attribute_taxonomy_term ) {
$attribute_taxonomy = $attribute_taxonomy_term->taxonomy;
$attribute_taxonomy_label = isset( $attribute_taxonomies_label[ $attribute_taxonomy ] ) ? $attribute_taxonomies_label[ $attribute_taxonomy ] : '';
if ( empty( $attribute_taxonomy_label ) ) {
continue;
}
$attribute_term_id = $attribute_taxonomy_term->term_id;
$attribute_term_name = $attribute_taxonomy_term->name;
$attribute_title = __( 'Attribute=', 'woocommerce-smart-coupons' ) . $attribute_taxonomy_label . ':' . __( 'Value=', 'woocommerce-smart-coupons' ) . $attribute_term_name;
$attribute_label = $attribute_taxonomy_label . ': ' . $attribute_term_name;
$attribute_options[ $attribute_term_id ] = array(
'title' => $attribute_title,
'label' => $attribute_label,
);
}
}
}
}
?>
<div class="options_group smart-coupons-field">
<p class="form-field">
<label for="wc_sc_product_attribute_ids"><?php echo esc_html__( 'Product attributes', 'woocommerce-smart-coupons' ); ?></label>
<select id="wc_sc_product_attribute_ids" name="wc_sc_product_attribute_ids[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No product attributes', 'woocommerce-smart-coupons' ); ?>">
<?php
if ( ! empty( $attribute_options ) ) {
foreach ( $attribute_options as $attribute_id => $attribute_data ) {
echo '<option title="' . esc_attr( $attribute_data['title'] ) . '" value="' . esc_attr( $attribute_id ) . '"' . esc_attr( selected( in_array( (string) $attribute_id, $product_attribute_ids, true ), true, false ) ) . '>' . esc_html( $attribute_data['label'] ) . '</option>';
}
}
?>
</select>
<?php
/* translators: Non product type coupon labels */
$tooltip_text = sprintf( esc_html__( 'Product attributes that the coupon will be applied to, or that need to be in the cart in order for the %s to be applied.', 'woocommerce-smart-coupons' ), $non_product_coupon_types_label );
echo wc_help_tip( $tooltip_text ); // phpcs:ignore
?>
</p>
</div>
<div class="options_group smart-coupons-field">
<p class="form-field">
<label for="wc_sc_exclude_product_attribute_ids"><?php echo esc_html__( 'Exclude attributes', 'woocommerce-smart-coupons' ); ?></label>
<select id="wc_sc_exclude_product_attribute_ids" name="wc_sc_exclude_product_attribute_ids[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No product attributes', 'woocommerce-smart-coupons' ); ?>">
<?php
if ( ! empty( $attribute_options ) ) {
foreach ( $attribute_options as $attribute_id => $attribute_data ) {
echo '<option title="' . esc_attr( $attribute_data['title'] ) . '" value="' . esc_attr( $attribute_id ) . '"' . esc_attr( selected( in_array( (string) $attribute_id, $exclude_product_attribute_ids, true ), true, false ) ) . '>' . esc_html( $attribute_data['label'] ) . '</option>';
}
}
?>
</select>
<?php
/* translators: Non product type coupon labels */
$tooltip_text = sprintf( esc_html__( 'Product attributes that the coupon will not be applied to, or that cannot be in the cart in order for the %s to be applied.', 'woocommerce-smart-coupons' ), $non_product_coupon_types_label );
echo wc_help_tip( $tooltip_text ); // phpcs:ignore
?>
</p>
</div>
<?php
}
/**
* Save coupon by product attribute data in meta
*
* @param Integer $post_id The coupon post ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function process_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$is_callable_coupon_update_meta = $this->is_callable( $coupon, 'update_meta_data' );
$product_attribute_ids = ( isset( $_POST['wc_sc_product_attribute_ids'] ) ) ? wc_clean( wp_unslash( $_POST['wc_sc_product_attribute_ids'] ) ) : array(); // phpcs:ignore
$product_attribute_ids = implode( '|', $product_attribute_ids ); // Store attribute ids as delimited data instead of serialized data.
if ( true === $is_callable_coupon_update_meta ) {
$coupon->update_meta_data( 'wc_sc_product_attribute_ids', $product_attribute_ids );
} else {
update_post_meta( $post_id, 'wc_sc_product_attribute_ids', $product_attribute_ids );
}
$exclude_product_attribute_ids = ( isset( $_POST['wc_sc_exclude_product_attribute_ids'] ) ) ? wc_clean( wp_unslash( $_POST['wc_sc_exclude_product_attribute_ids'] ) ) : array(); // phpcs:ignore
$exclude_product_attribute_ids = implode( '|', $exclude_product_attribute_ids ); // Store attribute ids as delimited data instead of serialized data.
if ( true === $is_callable_coupon_update_meta ) {
$coupon->update_meta_data( 'wc_sc_exclude_product_attribute_ids', $exclude_product_attribute_ids );
} else {
update_post_meta( $post_id, 'wc_sc_exclude_product_attribute_ids', $exclude_product_attribute_ids );
}
if ( $this->is_callable( $coupon, 'save' ) ) {
$coupon->save();
}
}
/**
* Function to validate coupons for against product attributes
*
* @param bool $valid Coupon validity.
* @param WC_Product|null $product Product object.
* @param WC_Coupon|null $coupon Coupon object.
* @param array|null $values Values.
* @return bool $valid
*/
public function validate( $valid = false, $product = null, $coupon = null, $values = null ) {
$backtrace = wp_list_pluck( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ), 'function' ); // phpcs:ignore
// If coupon is already invalid, no need for further checks.
// Ignore this check if the discount type is a non-product-type discount.
if ( true !== $valid && ! in_array( 'handle_non_product_type_coupons', $backtrace, true ) ) {
return $valid;
}
if ( empty( $product ) || empty( $coupon ) ) {
return $valid;
}
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
}
if ( ! empty( $coupon_id ) ) {
$coupon = ( ! empty( $coupon_id ) ) ? new WC_Coupon( $coupon_id ) : null;
if ( $this->is_callable( $coupon, 'get_meta' ) ) {
$product_attribute_ids = $coupon->get_meta( 'wc_sc_product_attribute_ids' );
$exclude_product_attribute_ids = $coupon->get_meta( 'wc_sc_exclude_product_attribute_ids' );
} else {
$product_attribute_ids = get_post_meta( $coupon_id, 'wc_sc_product_attribute_ids', true );
$exclude_product_attribute_ids = get_post_meta( $coupon_id, 'wc_sc_exclude_product_attribute_ids', true );
}
if ( ! empty( $product_attribute_ids ) || ! empty( $exclude_product_attribute_ids ) ) {
$current_product_attribute_ids = $this->get_product_attributes( $product );
if ( ! empty( $product_attribute_ids ) ) {
$product_attribute_ids = explode( '|', $product_attribute_ids );
}
$product_attribute_found = true;
if ( ! empty( $product_attribute_ids ) && is_array( $product_attribute_ids ) ) {
$common_attribute_ids = array_intersect( $product_attribute_ids, $current_product_attribute_ids );
if ( count( $common_attribute_ids ) > 0 ) {
$product_attribute_found = true;
} else {
$product_attribute_found = false;
}
}
if ( ! empty( $exclude_product_attribute_ids ) ) {
$exclude_product_attribute_ids = explode( '|', $exclude_product_attribute_ids );
}
$exclude_attribute_found = false;
if ( ! empty( $exclude_product_attribute_ids ) && is_array( $exclude_product_attribute_ids ) ) {
$common_exclude_attribute_ids = array_intersect( $exclude_product_attribute_ids, $current_product_attribute_ids );
if ( count( $common_exclude_attribute_ids ) > 0 ) {
$exclude_attribute_found = true;
} else {
$exclude_attribute_found = false;
}
}
if ( false === $product_attribute_found && false === $exclude_attribute_found ) {
$product_parent_id = is_callable( array( $product, 'get_parent_id' ) ) ? $product->get_parent_id() : 0;
if ( ! empty( $product_parent_id ) ) {
$parent_product = ( function_exists( 'wc_get_product' ) ) ? wc_get_product( $product_parent_id ) : null;
if ( ! empty( $parent_product ) ) {
$parent_product_attribute_ids = $this->get_product_attributes( $parent_product );
if ( apply_filters( 'wc_sc_check_parent_attributes', true, $product ) && ! empty( $product_attribute_ids ) && is_array( $product_attribute_ids ) ) {
$parent_product_attribute_id = array_intersect( $product_attribute_ids, $parent_product_attribute_ids );
if ( count( $parent_product_attribute_id ) > 0 ) {
$product_attribute_found = true;
} else {
$product_attribute_found = false;
}
}
if ( apply_filters( 'wc_sc_check_parent_attributes', true, $product ) && ! empty( $exclude_product_attribute_ids ) && is_array( $exclude_product_attribute_ids ) ) {
$exclude_parent_product_attribute_id = array_intersect( $exclude_product_attribute_ids, $parent_product_attribute_ids );
if ( count( $exclude_parent_product_attribute_id ) > 0 ) {
$exclude_attribute_found = true;
} else {
$exclude_attribute_found = false;
}
}
}
}
}
$valid = ( $product_attribute_found && ! $exclude_attribute_found ) ? true : false;
}
}
return $valid;
}
/**
* Function to get product attributes of a given product.
*
* @param WC_Product $product Product.
* @return array $product_attributes_ids IDs of product attributes
*/
public function get_product_attributes( $product = null ) {
$product_attributes_ids = array();
if ( ! is_a( $product, 'WC_Product' ) ) {
// Check if product id has been passed.
if ( is_numeric( $product ) ) {
$product = wc_get_product( $product );
}
}
if ( ! is_a( $product, 'WC_Product' ) ) {
return $product_attribute_ids;
}
$product_attributes = $product->get_attributes();
if ( ! empty( $product_attributes ) ) {
if ( true === $product->is_type( 'variation' ) ) {
foreach ( $product_attributes as $variation_taxonomy => $variation_slug ) {
$variation_attribute = get_term_by( 'slug', $variation_slug, $variation_taxonomy );
if ( is_object( $variation_attribute ) ) {
$product_attributes_ids[] = $variation_attribute->term_id;
}
}
} else {
$product_id = ( is_object( $product ) && is_callable( array( $product, 'get_id' ) ) ) ? $product->get_id() : 0;
if ( ! empty( $product_id ) ) {
$is_variable = $product->is_type( 'variable' );
foreach ( $product_attributes as $attribute ) {
if ( true === $is_variable && isset( $attribute['is_variation'] ) && ! empty( $attribute['is_variation'] ) ) {
continue;
}
if ( isset( $attribute['is_taxonomy'] ) && ! empty( $attribute['is_taxonomy'] ) ) {
$attribute_taxonomy_name = $attribute['name'];
$product_term_ids = wc_get_product_terms( $product_id, $attribute_taxonomy_name, array( 'fields' => 'ids' ) );
if ( ! empty( $product_term_ids ) && is_array( $product_term_ids ) ) {
foreach ( $product_term_ids as $product_term_id ) {
$product_attributes_ids[] = $product_term_id;
}
}
}
}
}
}
}
return $product_attributes_ids;
}
/**
* Function to validate non product type coupons against product attribute restriction
* We need to remove coupon if it does not pass attribute validation even for single cart item in case of non product type coupons e.g fixed_cart, smart_coupon since these coupon type require all products in the cart to be valid
*
* @param boolean $valid Coupon validity.
* @param WC_Coupon $coupon Coupon object.
* @param WC_Discounts $discounts Discounts object.
* @throws Exception Validation exception.
* @return boolean $valid Coupon validity
*/
public function handle_non_product_type_coupons( $valid = true, $coupon = null, $discounts = null ) {
// If coupon is already invalid, no need for further checks.
if ( true !== $valid ) {
return $valid;
}
if ( ! is_a( $coupon, 'WC_Coupon' ) ) {
return $valid;
}
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
$discount_type = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
}
if ( ! empty( $coupon_id ) ) {
if ( $this->is_callable( $coupon, 'get_meta' ) ) {
$product_attribute_ids = $coupon->get_meta( 'wc_sc_product_attribute_ids' );
$exclude_product_attribute_ids = $coupon->get_meta( 'wc_sc_exclude_product_attribute_ids' );
} else {
$product_attribute_ids = get_post_meta( $coupon_id, 'wc_sc_product_attribute_ids', true );
$exclude_product_attribute_ids = get_post_meta( $coupon_id, 'wc_sc_exclude_product_attribute_ids', true );
}
// If product attributes are not set in coupon, stop further processing and return from here.
if ( empty( $product_attribute_ids ) && empty( $exclude_product_attribute_ids ) ) {
return $valid;
}
} else {
return $valid;
}
$product_coupon_types = wc_get_product_coupon_types();
// Proceed if it is non product type coupon.
if ( ! in_array( $discount_type, $product_coupon_types, true ) ) {
if ( class_exists( 'WC_Discounts' ) && isset( WC()->cart ) ) {
$wc_cart = WC()->cart;
$wc_discounts = new WC_Discounts( $wc_cart );
$items_to_validate = array();
if ( is_callable( array( $wc_discounts, 'get_items_to_validate' ) ) ) {
$items_to_validate = $wc_discounts->get_items_to_validate();
} elseif ( is_callable( array( $wc_discounts, 'get_items' ) ) ) {
$items_to_validate = $wc_discounts->get_items();
} elseif ( isset( $wc_discounts->items ) && is_array( $wc_discounts->items ) ) {
$items_to_validate = $wc_discounts->items;
}
if ( ! empty( $items_to_validate ) && is_array( $items_to_validate ) ) {
$valid_products = array();
$invalid_products = array();
foreach ( $items_to_validate as $item ) {
$cart_item = clone $item; // Clone the item so changes to wc_discounts item do not affect the originals.
$item_product = isset( $cart_item->product ) ? $cart_item->product : null;
$item_object = isset( $cart_item->object ) ? $cart_item->object : null;
if ( ! is_null( $item_product ) && ! is_null( $item_object ) ) {
if ( $coupon->is_valid_for_product( $item_product, $item_object ) ) {
$valid_products[] = $item_product;
} else {
$invalid_products[] = $item_product;
}
}
}
// If cart does not have any valid product then throw Exception.
if ( 0 === count( $valid_products ) ) {
$error_message = __( 'Sorry, this coupon is not applicable to selected products.', 'woocommerce-smart-coupons' );
$error_code = defined( 'E_WC_COUPON_NOT_APPLICABLE' ) ? E_WC_COUPON_NOT_APPLICABLE : 0;
throw new Exception( $error_message, $error_code );
} elseif ( count( $invalid_products ) > 0 && ! empty( $exclude_product_attribute_ids ) ) {
$exclude_product_attribute_ids = explode( '|', $exclude_product_attribute_ids );
$excluded_products = array();
foreach ( $invalid_products as $invalid_product ) {
$product_attributes = $this->get_product_attributes( $invalid_product );
if ( ! empty( $product_attributes ) && is_array( $product_attributes ) ) {
$common_exclude_attribute_ids = array_intersect( $exclude_product_attribute_ids, $product_attributes );
if ( count( $common_exclude_attribute_ids ) > 0 ) {
$excluded_products[] = $invalid_product->get_name();
} else {
$product_parent_id = is_callable( array( $invalid_product, 'get_parent_id' ) ) ? $invalid_product->get_parent_id() : 0;
if ( ! empty( $product_parent_id ) ) {
$parent_product = ( function_exists( 'wc_get_product' ) ) ? wc_get_product( $product_parent_id ) : '';
if ( ! empty( $parent_product ) ) {
$parent_product_attribute_ids = $this->get_product_attributes( $parent_product );
if ( apply_filters( 'wc_sc_check_parent_attributes', true, $invalid_product ) && ! empty( $exclude_product_attribute_ids ) && is_array( $exclude_product_attribute_ids ) ) {
$exclude_parent_product_attribute_id = array_intersect( $exclude_product_attribute_ids, $parent_product_attribute_ids );
if ( count( $exclude_parent_product_attribute_id ) > 0 ) {
$excluded_products[] = $invalid_product->get_name();
}
}
}
}
}
}
}
if ( count( $excluded_products ) > 0 ) {
// If cart contains any excluded product and it is being excluded from our excluded product attributes then throw Exception.
/* translators: 1. Singular/plural label for product(s) 2. Excluded product names */
$error_message = sprintf( __( 'Sorry, this coupon is not applicable to the %1$s: %2$s.', 'woocommerce-smart-coupons' ), _n( 'product', 'products', count( $excluded_products ), 'woocommerce-smart-coupons' ), implode( ', ', $excluded_products ) );
$error_code = defined( 'E_WC_COUPON_EXCLUDED_PRODUCTS' ) ? E_WC_COUPON_EXCLUDED_PRODUCTS : 0;
throw new Exception( $error_message, $error_code );
}
}
}
}
}
return $valid;
}
/**
* Add meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$headers['wc_sc_product_attribute_ids'] = __( 'Product Attributes', 'woocommerce-smart-coupons' );
$headers['wc_sc_exclude_product_attribute_ids'] = __( 'Exclude Attributes', 'woocommerce-smart-coupons' );
return $headers;
}
/**
* Post meta defaults for product attribute ids meta
*
* @param array $defaults Existing postmeta defaults.
* @return array $defaults Modified postmeta defaults
*/
public function postmeta_defaults( $defaults = array() ) {
$defaults['wc_sc_product_attribute_ids'] = '';
$defaults['wc_sc_exclude_product_attribute_ids'] = '';
return $defaults;
}
/**
* Make meta data of product attribute ids protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected = false, $meta_key = '', $meta_type = '' ) {
$sc_product_attribute_keys = array(
'wc_sc_product_attribute_ids',
'wc_sc_exclude_product_attribute_ids',
);
if ( in_array( $meta_key, $sc_product_attribute_keys, true ) ) {
return true;
}
return $protected;
}
/**
* Add product's attribute in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array Modified data
*/
public function generate_coupon_attribute_meta( $data = array(), $post = array() ) {
$product_attribute_ids = ( isset( $post['wc_sc_product_attribute_ids'] ) ) ? wc_clean( wp_unslash( $post['wc_sc_product_attribute_ids'] ) ) : array(); // phpcs:ignore
$data['wc_sc_product_attribute_ids'] = implode( '|', $product_attribute_ids ); // Store attribute ids as delimited data instead of serialized data.
$exclude_product_attribute_ids = ( isset( $post['wc_sc_exclude_product_attribute_ids'] ) ) ? wc_clean( wp_unslash( $post['wc_sc_exclude_product_attribute_ids'] ) ) : array(); // phpcs:ignore
$data['wc_sc_exclude_product_attribute_ids'] = implode( '|', $exclude_product_attribute_ids ); // Store attribute ids as delimited data instead of serialized data.
return $data;
}
/**
* Function to copy product's attribute meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_attributes_meta( $args = array() ) {
$new_coupon_id = ( ! empty( $args['new_coupon_id'] ) ) ? absint( $args['new_coupon_id'] ) : 0;
$coupon = ( ! empty( $args['ref_coupon'] ) ) ? $args['ref_coupon'] : false;
if ( empty( $new_coupon_id ) || empty( $coupon ) ) {
return;
}
if ( $this->is_wc_gte_30() ) {
$product_attribute_ids = $coupon->get_meta( 'wc_sc_product_attribute_ids' );
$exclude_product_attribute_ids = $coupon->get_meta( 'wc_sc_exclude_product_attribute_ids' );
} else {
$old_coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$product_attribute_ids = get_post_meta( $old_coupon_id, 'wc_sc_product_attribute_ids', true );
$exclude_product_attribute_ids = get_post_meta( $old_coupon_id, 'wc_sc_exclude_product_attribute_ids', true );
}
$new_coupon = new WC_Coupon( $new_coupon_id );
if ( $this->is_callable( $new_coupon, 'update_meta_data' ) && $this->is_callable( $new_coupon, 'save' ) ) {
$new_coupon->update_meta_data( 'wc_sc_product_attribute_ids', $product_attribute_ids );
$new_coupon->update_meta_data( 'wc_sc_exclude_product_attribute_ids', $exclude_product_attribute_ids );
$new_coupon->save();
} else {
update_post_meta( $new_coupon_id, 'wc_sc_product_attribute_ids', $product_attribute_ids );
update_post_meta( $new_coupon_id, 'wc_sc_exclude_product_attribute_ids', $exclude_product_attribute_ids );
}
}
}
}
WC_SC_Coupons_By_Product_Attribute::get_instance();

View File

@@ -0,0 +1,394 @@
<?php
/**
* Class to handle feature Coupons By Shipping Method
*
* @author StoreApps
* @category Admin
* @package wocommerce-smart-coupons/includes
* @version 1.8.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupons_By_Shipping_Method' ) ) {
/**
* Class WC_SC_Coupons_By_Shipping_Method
*/
class WC_SC_Coupons_By_Shipping_Method {
/**
* Variable to hold instance of this class
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_coupon_options_usage_restriction', array( $this, 'usage_restriction' ), 10, 2 );
add_action( 'woocommerce_coupon_options_save', array( $this, 'process_meta' ), 10, 2 );
add_filter( 'woocommerce_coupon_is_valid', array( $this, 'validate' ), 11, 3 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'wc_sc_export_coupon_meta', array( $this, 'export_coupon_meta_data' ), 10, 2 );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'wc_sc_process_coupon_meta_value_for_import', array( $this, 'process_coupon_meta_value_for_import' ), 10, 2 );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_shipping_method_meta' ) );
// Register the action for shipping change via Block API.
add_action( 'woocommerce_store_api_cart_select_shipping_rate', array( $this, 'wc_blocks_sc_shipping_change_auto_apply_coupon' ), 10, 3 );
}
/**
* Get single instance of this class
*
* @return this class Singleton object of this class
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name = '', $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Display field for coupon by shipping method
*
* @param integer $coupon_id The coupon id.
* @param WC_Coupon $coupon The coupon object.
*/
public function usage_restriction( $coupon_id = 0, $coupon = null ) {
$shipping_method_ids = array();
if ( ! empty( $coupon_id ) ) {
$shipping_method_ids = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_sc_shipping_method_ids' ) : $this->get_post_meta( $coupon_id, 'wc_sc_shipping_method_ids', true );
if ( empty( $shipping_method_ids ) || ! is_array( $shipping_method_ids ) ) {
$shipping_method_ids = array();
}
}
$available_shipping_methods = WC()->shipping->get_shipping_methods();
?>
<div class="options_group smart-coupons-field">
<p class="form-field">
<label for="wc_sc_shipping_method_ids"><?php echo esc_html__( 'Shipping methods', 'woocommerce-smart-coupons' ); ?></label>
<select id="wc_sc_shipping_method_ids" name="wc_sc_shipping_method_ids[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No shipping methods', 'woocommerce-smart-coupons' ); ?>">
<?php
if ( is_array( $available_shipping_methods ) && ! empty( $available_shipping_methods ) ) {
foreach ( $available_shipping_methods as $shipping_method ) {
echo '<option value="' . esc_attr( $shipping_method->id ) . '"' . esc_attr( selected( in_array( $shipping_method->id, $shipping_method_ids, true ), true, false ) ) . '>' . esc_html( $shipping_method->get_method_title() ) . '</option>';
}
}
?>
</select>
<?php
$tooltip_text = esc_html__( 'Shipping methods that must be selected during checkout for this coupon to be valid.', 'woocommerce-smart-coupons' );
echo wc_help_tip( $tooltip_text ); // phpcs:ignore
?>
</p>
</div>
<?php
}
/**
* Save coupon by shipping method data in meta
*
* @param Integer $post_id The coupon post ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function process_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$shipping_method_ids = ( isset( $_POST['wc_sc_shipping_method_ids'] ) ) ? wc_clean( wp_unslash( $_POST['wc_sc_shipping_method_ids'] ) ) : array(); // phpcs:ignore
if ( $this->is_callable( $coupon, 'update_meta_data' ) && $this->is_callable( $coupon, 'save' ) ) {
$coupon->update_meta_data( 'wc_sc_shipping_method_ids', $shipping_method_ids );
$coupon->save();
} else {
$this->update_post_meta( $post_id, 'wc_sc_shipping_method_ids', $shipping_method_ids );
}
}
/**
* Validate the coupon based on shipping method
*
* @param boolean $valid Is valid or not.
* @param WC_Coupon $coupon The coupon object.
* @param WC_Discounts $discounts The discount object.
*
* @throws Exception If the coupon is invalid.
* @return boolean Is valid or not
*/
public function validate( $valid = false, $coupon = object, $discounts = null ) {
// If coupon is already invalid, no need for further checks.
if ( false === $valid ) {
return $valid;
}
$coupon_id = ( $this->is_wc_gte_30() ) ? $coupon->get_id() : $coupon->id;
$shipping_method_ids = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_sc_shipping_method_ids' ) : $this->get_post_meta( $coupon_id, 'wc_sc_shipping_method_ids', true );
if ( is_array( $shipping_method_ids ) && ! empty( $shipping_method_ids ) ) {
$chosen_shipping_method_data = WC()->session->__isset( 'chosen_shipping_methods' ) ? WC()->session->get( 'chosen_shipping_methods' ) : '';
$chosen_shipping_method_string = is_array( $chosen_shipping_method_data ) && ! empty( $chosen_shipping_method_data ) ? $chosen_shipping_method_data[0] : '';
if ( ! empty( $chosen_shipping_method_string ) ) {
$chosen_shipping_method_string = explode( ':', $chosen_shipping_method_string );
$chosen_shipping_method_id = $chosen_shipping_method_string[0];
if ( ! in_array( $chosen_shipping_method_id, $shipping_method_ids, true ) ) {
$wc_shipping_packages = ( is_callable( array( WC()->shipping, 'get_packages' ) ) ) ? WC()->shipping->get_packages() : null;
if ( empty( $wc_shipping_packages ) && is_callable( array( WC()->cart, 'calculate_shipping' ) ) ) {
WC()->cart->calculate_shipping();
}
$chosen_shipping_method_rate_id = is_array( $chosen_shipping_method_data ) && ! empty( $chosen_shipping_method_data ) ? $chosen_shipping_method_data[0] : '';
$shipping_method_id = '';
$available_shipping_packages = ( is_callable( array( WC()->shipping, 'get_packages' ) ) ) ? WC()->shipping->get_packages() : '';
if ( ! empty( $available_shipping_packages ) ) {
foreach ( $available_shipping_packages as $key => $package ) {
if ( ! empty( $shipping_method_id ) ) {
break;
}
// Loop through Shipping rates.
if ( isset( $package['rates'] ) && ! empty( $package['rates'] ) ) {
foreach ( $package['rates'] as $rate_id => $rate ) {
if ( $chosen_shipping_method_rate_id === $rate_id ) {
$shipping_method_id = ( is_callable( array( $rate, 'get_method_id' ) ) ) ? $rate->get_method_id() : '';
break;
}
}
}
}
if ( ! in_array( $shipping_method_id, $shipping_method_ids, true ) ) {
if ( ! apply_filters( 'wc_sc_coupon_validate_shipping_method', false, $chosen_shipping_method_id, $shipping_method_ids ) ) {
throw new Exception( __( 'This coupon is not valid for selected shipping method.', 'woocommerce-smart-coupons' ) );
}
}
} else {
if ( ! apply_filters( 'wc_sc_coupon_validate_shipping_method', false, $chosen_shipping_method_id, $shipping_method_ids ) ) {
throw new Exception( __( 'This coupon is not valid for selected shipping method.', 'woocommerce-smart-coupons' ) );
}
}
}
}
}
return $valid;
}
/**
* Add meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$headers['wc_sc_shipping_method_ids'] = __( 'Shipping methods', 'woocommerce-smart-coupons' );
return $headers;
}
/**
* Function to handle coupon meta data during export of existing coupons
*
* @param mixed $meta_value The meta value.
* @param array $args Additional arguments.
* @return string Processed meta value
*/
public function export_coupon_meta_data( $meta_value = '', $args = array() ) {
if ( ! empty( $args['meta_key'] ) && 'wc_sc_shipping_method_ids' === $args['meta_key'] ) {
if ( isset( $args['meta_value'] ) && ! empty( $args['meta_value'] ) ) {
$shipping_method_ids = maybe_unserialize( stripslashes( $args['meta_value'] ) );
if ( is_array( $shipping_method_ids ) && ! empty( $shipping_method_ids ) ) {
$shipping_method_titles = $this->get_shipping_method_titles_by_ids( $shipping_method_ids );
if ( is_array( $shipping_method_titles ) && ! empty( $shipping_method_titles ) ) {
$meta_value = implode( '|', wc_clean( wp_unslash( $shipping_method_titles ) ) ); // Replace shipping method ids with their respective method titles.
}
}
}
}
return $meta_value;
}
/**
* Post meta defaults for shipping method ids meta
*
* @param array $defaults Existing postmeta defaults.
* @return array $defaults Modified postmeta defaults
*/
public function postmeta_defaults( $defaults = array() ) {
$defaults['wc_sc_shipping_method_ids'] = '';
return $defaults;
}
/**
* Add shipping method's meta with value in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array $data Modified row data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
$shipping_method_titles = '';
if ( ! empty( $post['wc_sc_shipping_method_ids'] ) && is_array( $post['wc_sc_shipping_method_ids'] ) ) {
$shipping_method_titles = $this->get_shipping_method_titles_by_ids( $post['wc_sc_shipping_method_ids'] );
if ( is_array( $shipping_method_titles ) && ! empty( $shipping_method_titles ) ) {
$shipping_method_titles = implode( '|', wc_clean( wp_unslash( $shipping_method_titles ) ) );
}
}
$data['wc_sc_shipping_method_ids'] = $shipping_method_titles; // Replace shipping method ids with their respective method titles.
return $data;
}
/**
* Function to get shipping method titles for given shipping method ids
*
* @param array $shipping_method_ids ids of shipping methods.
* @return array $shipping_method_titles titles of shipping methods
*/
public function get_shipping_method_titles_by_ids( $shipping_method_ids = array() ) {
$shipping_method_titles = array();
if ( is_array( $shipping_method_ids ) && ! empty( $shipping_method_ids ) ) {
$available_shipping_methods = WC()->shipping->load_shipping_methods();
foreach ( $shipping_method_ids as $index => $shipping_method_id ) {
$shipping_method = ( isset( $available_shipping_methods[ $shipping_method_id ] ) && ! empty( $available_shipping_methods[ $shipping_method_id ] ) ) ? $available_shipping_methods[ $shipping_method_id ] : '';
if ( ! empty( $shipping_method ) && is_a( $shipping_method, 'WC_Shipping_Method' ) ) {
$shipping_method_title = is_callable( array( $shipping_method, 'get_method_title' ) ) ? $shipping_method->get_method_title() : '';
if ( ! empty( $shipping_method_title ) ) {
$shipping_method_titles[ $index ] = $shipping_method_title; // Replace shipping method id with it's repective title.
} else {
$shipping_method_titles[ $index ] = $shipping_method->id; // In case of empty shipping method title replace it with method id.
}
}
}
}
return $shipping_method_titles;
}
/**
* Process coupon meta value for import
*
* @param mixed $meta_value The meta value.
* @param array $args Additional Arguments.
* @return mixed $meta_value
*/
public function process_coupon_meta_value_for_import( $meta_value = null, $args = array() ) {
if ( ! empty( $args['meta_key'] ) && 'wc_sc_shipping_method_ids' === $args['meta_key'] ) {
$meta_value = ( ! empty( $args['postmeta']['wc_sc_shipping_method_ids'] ) ) ? explode( '|', wc_clean( wp_unslash( $args['postmeta']['wc_sc_shipping_method_ids'] ) ) ) : array();
if ( is_array( $meta_value ) && ! empty( $meta_value ) ) {
$available_shipping_methods = WC()->shipping->load_shipping_methods();
if ( is_array( $available_shipping_methods ) && ! empty( $available_shipping_methods ) ) {
foreach ( $meta_value as $index => $shipping_method_title ) {
foreach ( $available_shipping_methods as $shipping_method ) {
$method_title = is_callable( array( $shipping_method, 'get_method_title' ) ) ? $shipping_method->get_method_title() : '';
if ( $method_title === $shipping_method_title && ! empty( $shipping_method->id ) ) {
$meta_value[ $index ] = $shipping_method->id; // Replace shipping method title with it's repective id.
}
}
}
}
}
}
return $meta_value;
}
/**
* Function to copy shipping method restriction meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_shipping_method_meta( $args = array() ) {
// Copy meta data to new coupon.
$this->copy_coupon_meta_data(
$args,
array( 'wc_sc_shipping_method_ids' )
);
}
/**
* Make meta data of shipping method ids protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected = false, $meta_key = '', $meta_type = '' ) {
if ( 'wc_sc_shipping_method_ids' === $meta_key ) {
return true;
}
return $protected;
}
/**
* WC Blocks on shipping change should trigger auto-apply coupon.
*
* @param string|null $package_id The sanitized ID of the package being updated. Null if all packages are being updated.
* @param string $rate_id The sanitized chosen rate ID for the package.
* @param \WP_REST_Request $request Full details about the request.
*/
public function wc_blocks_sc_shipping_change_auto_apply_coupon( $package_id, $rate_id, $request ) {
$class_auto_apply = WC_SC_Auto_Apply_Coupon::get_instance();
$class_auto_apply->auto_apply_coupons();
}
}
}
WC_SC_Coupons_By_Shipping_Method::get_instance();

View File

@@ -0,0 +1,880 @@
<?php
/**
* Class to handle feature Coupons By Taxonomy
*
* @author StoreApps
* @category Admin
* @package wocommerce-smart-coupons/includes
* @since 4.13.0
* @version 1.8.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupons_By_Taxonomy' ) ) {
/**
* Class WC_SC_Coupons_By_Taxonomy
*/
class WC_SC_Coupons_By_Taxonomy {
/**
* Variable to hold instance of this class
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_coupon_options_usage_restriction', array( $this, 'usage_restriction' ), 99, 2 );
add_action( 'wp_ajax_taxonomy_restriction_row_html', array( $this, 'ajax_taxonomy_restriction_row_html' ) );
add_action( 'wp_ajax_taxonomy_restriction_select_tag_html', array( $this, 'ajax_taxonomy_restriction_select_tag_html' ) );
add_action( 'wp_ajax_default_taxonomy_restriction_row_html', array( $this, 'ajax_default_taxonomy_restriction_row_html' ) );
add_action( 'admin_footer', array( $this, 'styles_and_scripts' ) );
add_action( 'woocommerce_coupon_options_save', array( $this, 'process_meta' ), 10, 2 );
add_filter( 'woocommerce_coupon_is_valid_for_product', array( $this, 'validate' ), 11, 4 );
add_filter( 'woocommerce_coupon_is_valid', array( $this, 'handle_non_product_type_coupons' ), 11, 3 );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_taxonomy_meta' ) );
add_filter( 'wc_sc_process_coupon_meta_value_for_import', array( $this, 'process_coupon_meta_value_for_import' ), 10, 2 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
}
/**
* Get single instance of this class
*
* @return this class Singleton object of this class
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name = '', $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Display field for coupon by payment method
*
* @param integer $coupon_id The coupon id.
* @param WC_Coupon $coupon The coupon object.
*/
public function usage_restriction( $coupon_id = 0, $coupon = null ) {
$taxonomy_to_label = $this->get_taxonomy_with_label();
$terms = $this->get_terms_grouped_by_taxonomy();
$operators = array(
'incl' => __( 'Include', 'woocommerce-smart-coupons' ),
'excl' => __( 'Exclude', 'woocommerce-smart-coupons' ),
);
$taxonomy_restrictions = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_sc_taxonomy_restrictions' ) : $this->get_post_meta( $coupon_id, 'wc_sc_taxonomy_restrictions', true );
?>
<div class="options_group smart-coupons-field wc_sc_taxonomy_restrictions">
<?php
if ( empty( $taxonomy_restrictions ) ) {
$this->get_default_taxonomy_restriction_row();
}
if ( ! empty( $taxonomy_restrictions ) ) {
$count = count( $taxonomy_restrictions );
for ( $i = 0; $i < $count; $i++ ) {
$args = array(
'index' => $i,
'taxonomy_restriction' => $taxonomy_restrictions[ $i ],
'taxonomy_to_label' => $taxonomy_to_label,
'operators' => $operators,
'terms' => $terms,
);
$this->get_taxonomy_restriction_row( $args );
}
}
?>
</div>
<?php
}
/**
* Get default taxonomy restriction row
*/
public function get_default_taxonomy_restriction_row() {
?>
<p class="form-field">
<label>
<?php
echo esc_html__( 'Taxonomy', 'woocommerce-smart-coupons' );
$tooltip_text = esc_html__( 'Product taxonomies that the coupon will be applicable for, or its availability in the cart in order for the "Fixed cart discount" to be applied, based on whether the taxonomies are included or excluded. All the taxonomies selected here, should be valid, for this coupon to be valid.', 'woocommerce-smart-coupons' );
echo wc_help_tip( $tooltip_text ); // phpcs:ignore
?>
</label>
<span id="wc_sc_add_taxonomy_row" class="button wc_sc_add_taxonomy_row" title="<?php echo esc_attr__( 'Add taxonomy restriction', 'woocommerce-smart-coupons' ); ?>"><?php echo esc_html__( 'Add taxonomy restriction', 'woocommerce-smart-coupons' ); ?></span>
</p>
<?php
}
/**
* Get taxonomy restriction row HTML via AJAX
*/
public function ajax_default_taxonomy_restriction_row_html() {
check_ajax_referer( 'wc-sc-default-taxonomy-restriction-row', 'security' );
$this->get_default_taxonomy_restriction_row();
die();
}
/**
* Get taxonomy restriction row
*
* @param array $args Arguments.
*/
public function get_taxonomy_restriction_row( $args = array() ) {
$index = ( ! empty( $args['index'] ) ) ? absint( $args['index'] ) : 0;
$taxonomy_restriction = ( ! empty( $args['taxonomy_restriction'] ) ) ? $args['taxonomy_restriction'] : array();
$taxonomy_to_label = ( ! empty( $args['taxonomy_to_label'] ) ) ? $args['taxonomy_to_label'] : array();
$terms = ( ! empty( $args['terms'] ) ) ? $args['terms'] : array();
$operators = ( ! empty( $args['operators'] ) ) ? $args['operators'] : array();
$tax = $taxonomy_restriction['tax'];
$op = $taxonomy_restriction['op'];
$value = $taxonomy_restriction['val'];
?>
<p class="form-field wc_sc_taxonomy_restrictions_row wc_sc_taxonomy_restrictions-<?php echo esc_attr( $index ); ?>">
<label>
<?php
if ( 0 === $index ) {
echo esc_html__( 'Taxonomy', 'woocommerce-smart-coupons' );
$tooltip_text = esc_html__( 'Product taxonomies that the coupon will be applicable for, or its availability in the cart in order for the "Fixed cart discount" to be applied, based on whether the taxonomies are included or excluded.', 'woocommerce-smart-coupons' );
echo wc_help_tip( $tooltip_text ); // phpcs:ignore
} else {
echo esc_html( ' ' );
}
?>
</label>
<?php
$args = array(
'index' => $index,
'column' => 'tax',
'all' => $taxonomy_to_label,
'selected' => $tax,
'width' => '140px',
);
$this->get_taxonomy_restriction_select_tag( $args );
?>
<?php
$args = array(
'index' => $index,
'column' => 'op',
'all' => $operators,
'selected' => $op,
'width' => '70px',
);
$this->get_taxonomy_restriction_select_tag( $args );
?>
<?php
$args = array(
'index' => $index,
'column' => 'val',
'all' => $terms[ $tax ],
'selected' => $value,
);
$this->get_taxonomy_restriction_select_tag( $args );
?>
<span id="wc_sc_add_taxonomy_row" class="button wc_sc_add_taxonomy_row dashicons dashicons-plus-alt2" title="<?php echo esc_attr__( 'Add taxonomy restriction', 'woocommerce-smart-coupons' ); ?>"></span><span id="remove_wc_sc_taxonomy_restrictions-<?php echo esc_attr( $index ); ?>" class="button remove_wc_sc_taxonomy_restrictions-<?php echo esc_attr( $index ); ?> dashicons dashicons-no-alt" title="<?php echo esc_attr__( 'Remove taxonomy restriction', 'woocommerce-smart-coupons' ); ?>"></span>
</p>
<?php
}
/**
* Draw taxonomy restriction select tag
*
* @param array $args Arguments.
*/
public function get_taxonomy_restriction_select_tag( $args = array() ) {
$index = ( ! empty( $args['index'] ) ) ? $args['index'] : 0;
$column = ( ! empty( $args['column'] ) ) ? $args['column'] : '';
$all = ( ! empty( $args['all'] ) ) ? $args['all'] : array();
$selected = ( ! empty( $args['selected'] ) ) ? $args['selected'] : array();
$width = ( ! empty( $args['width'] ) ) ? $args['width'] : '350px';
?>
<select name="wc_sc_taxonomy_restrictions[<?php echo esc_attr( $index ); ?>][<?php echo esc_attr( $column ); ?>]<?php echo esc_attr( 'val' === $column ? '[]' : '' ); ?>" id="wc_sc_taxonomy_restrictions-<?php echo esc_attr( $index ); ?>-<?php echo esc_attr( $column ); ?>" style="min-width: <?php echo esc_attr( $width ); ?>;" class="wc-enhanced-select" <?php echo ( 'val' === $column ? 'multiple="multiple"' : '' ); ?> tabindex="-1" aria-hidden="true">
<?php
foreach ( $all as $key => $val ) {
?>
<option value="<?php echo esc_attr( $key ); ?>"
<?php
if ( is_array( $selected ) ) {
selected( in_array( (string) $key, $selected, true ), true );
} else {
selected( $selected, (string) $key );
}
?>
><?php echo esc_html( ucfirst( $val ) ); ?></option>
<?php
}
?>
</select>
<?php
}
/**
* Get taxonomy restriction row HTML via AJAX
*/
public function ajax_taxonomy_restriction_select_tag_html() {
check_ajax_referer( 'wc-sc-taxonomy-restriction-select-tag', 'security' );
$index = ( ! empty( $_POST['index'] ) ) ? sanitize_text_field( wp_unslash( $_POST['index'] ) ) : 0;
$tax = ( ! empty( $_POST['tax'] ) ) ? sanitize_text_field( wp_unslash( $_POST['tax'] ) ) : '';
$terms = $this->get_terms_grouped_by_taxonomy();
$args = array(
'index' => $index,
'column' => 'val',
'all' => $terms[ $tax ],
);
$this->get_taxonomy_restriction_select_tag( $args );
die();
}
/**
* Get taxonomy restriction row HTML via AJAX
*/
public function ajax_taxonomy_restriction_row_html() {
check_ajax_referer( 'wc-sc-taxonomy-restriction-row', 'security' );
$index = ( ! empty( $_POST['index'] ) ) ? sanitize_text_field( wp_unslash( $_POST['index'] ) ) : 0;
$taxonomy_to_label = $this->get_taxonomy_with_label();
$terms = $this->get_terms_grouped_by_taxonomy();
$operators = array(
'incl' => __( 'Include', 'woocommerce-smart-coupons' ),
'excl' => __( 'Exclude', 'woocommerce-smart-coupons' ),
);
$tax = current( array_keys( $taxonomy_to_label ) );
$op = current( array_keys( $operators ) );
$args = array(
'index' => $index,
'taxonomy_restriction' => array(
'tax' => $tax,
'op' => $op,
'val' => array(),
),
'taxonomy_to_label' => $taxonomy_to_label,
'operators' => $operators,
'terms' => $terms,
);
$this->get_taxonomy_restriction_row( $args );
die();
}
/**
* Styles and scripts
*/
public function styles_and_scripts() {
if ( ! wp_script_is( 'jquery' ) ) {
wp_enqueue_script( 'jquery' );
}
?>
<style type="text/css">
.options_group.wc_sc_taxonomy_restrictions span.select2.select2-container {
margin: 0 1em 1em 0;
}
.options_group.wc_sc_taxonomy_restrictions .button {
margin: 0 0 0.5em 0.5em;
}
.options_group.wc_sc_taxonomy_restrictions .button.dashicons {
width: auto;
}
.options_group.wc_sc_taxonomy_restrictions .dashicons.dashicons-no-alt::before {
opacity: 0.5;
font-weight: 100;
}
.options_group.wc_sc_taxonomy_restrictions .dashicons {
vertical-align: middle;
}
.options_group.wc_sc_taxonomy_restrictions .woocommerce-help-tip {
float: right;
margin: 0 0.4em;
transform: translateY(25%);
}
</style>
<script type="text/javascript">
jQuery(function(){
function wc_sc_taxonomy_restrictions_field_loaded() {
jQuery('.wc_sc_taxonomy_restrictions').find('.wc_sc_add_taxonomy_row').filter(':not(:last)').remove();
}
function wc_sc_add_taxonomy_clicked() {
jQuery('.wc_sc_taxonomy_restrictions').find('.wc_sc_add_taxonomy_row').remove();
jQuery('.wc_sc_taxonomy_restrictions').find('p.form-field').filter(':not(p.wc_sc_taxonomy_restrictions_row)').remove();
}
wc_sc_taxonomy_restrictions_field_loaded();
jQuery('body').on('click', '#wc_sc_add_taxonomy_row', function(){
var count = jQuery('.wc_sc_taxonomy_restrictions').find('.wc_sc_taxonomy_restrictions_row').length;
jQuery.ajax({
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
type: 'post',
dataType: 'html',
data: {
action: 'taxonomy_restriction_row_html',
security: '<?php echo esc_html( wp_create_nonce( 'wc-sc-taxonomy-restriction-row' ) ); ?>',
index: count
},
success: function( response ){
if ( response != undefined && response != '' ) {
wc_sc_add_taxonomy_clicked();
jQuery('.wc_sc_taxonomy_restrictions').append(response);
jQuery(document.body).trigger('wc-enhanced-select-init');
if ( count <= 0 ) {
jQuery(document.body).trigger('init_tooltips');
}
}
}
});
});
jQuery('body').on('change', '[id^="wc_sc_taxonomy_restrictions-"][id$="-tax"]', function(){
var current_element = jQuery(this);
var element_id = current_element.attr('id');
var selected_value = current_element.val();
var index = element_id.replace('wc_sc_taxonomy_restrictions-', '').replace('-tax', '');
jQuery.ajax({
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
type: 'post',
dataType: 'html',
data: {
action: 'taxonomy_restriction_select_tag_html',
security: '<?php echo esc_html( wp_create_nonce( 'wc-sc-taxonomy-restriction-select-tag' ) ); ?>',
index: index,
tax: selected_value
},
success: function( response ){
if ( response != undefined && response != '' ) {
jQuery('#wc_sc_taxonomy_restrictions-'+index+'-val').selectWoo('destroy').remove();
jQuery('#wc_sc_taxonomy_restrictions-'+index+'-op').parent().append(response);
jQuery(document.body).trigger('wc-enhanced-select-init');
}
}
});
});
jQuery('body').on('click', '[id^="remove_wc_sc_taxonomy_restrictions-"]', function(){
var current_element = jQuery(this);
if ( current_element.parent().find( '#wc_sc_add_taxonomy_row' ).length > 0 ) {
current_element.parent().prev().find('[id^=remove_wc_sc_taxonomy_restrictions-]').before(current_element.parent().find('#wc_sc_add_taxonomy_row'));
}
if ( current_element.parent().find( '.woocommerce-help-tip' ).length > 0 ) {
current_element.parent().next().find('label').replaceWith(current_element.parent().find('label'));
}
current_element.parent().find('.wc-enhanced-select').selectWoo('destroy');
current_element.parent().remove();
var count = jQuery('.wc_sc_taxonomy_restrictions').find('.wc_sc_taxonomy_restrictions_row').length;
if ( count <= 0 ) {
jQuery.ajax({
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
type: 'post',
dataType: 'html',
data: {
action: 'default_taxonomy_restriction_row_html',
security: '<?php echo esc_html( wp_create_nonce( 'wc-sc-default-taxonomy-restriction-row' ) ); ?>'
},
success: function( response ){
if ( response != undefined && response != '' ) {
jQuery('.wc_sc_taxonomy_restrictions').append(response);
jQuery(document.body).trigger('wc-enhanced-select-init');
jQuery(document.body).trigger('init_tooltips');
}
}
});
}
});
});
</script>
<?php
}
/**
* Get taxonomy with label
*
* @return array
*/
public function get_taxonomy_with_label() {
global $wp_taxonomies;
$taxonomy_to_label = array();
$include_taxonomy = array(
'product_type',
'product_visibility',
'product_tag',
'product_shipping_class',
);
$include_taxonomy = apply_filters( 'wc_sc_include_taxonomy_for_restrictions', $include_taxonomy, array( 'source' => $this ) );
if ( ! empty( $wp_taxonomies ) ) {
foreach ( $wp_taxonomies as $taxonomy => $wp_taxonomy ) {
if ( in_array( $taxonomy, $include_taxonomy, true ) ) {
$taxonomy_to_label[ $taxonomy ] = $wp_taxonomy->label;
}
}
}
return $taxonomy_to_label;
}
/**
* Get terms grouped by taxonomy
*
* @return array
*/
public function get_terms_grouped_by_taxonomy() {
$terms_by_taxonomy = array();
$include_taxonomy = array(
'product_type',
'product_visibility',
'product_tag',
'product_shipping_class',
);
$include_taxonomy = apply_filters( 'wc_sc_include_taxonomy_for_restrictions', $include_taxonomy, array( 'source' => $this ) );
$args = array(
'taxonomy' => $include_taxonomy,
'hide_empty' => false,
);
$terms = get_terms( $args );
if ( ! empty( $terms ) ) {
foreach ( $terms as $term ) {
if ( empty( $terms_by_taxonomy[ $term->taxonomy ] ) || ! is_array( $terms_by_taxonomy[ $term->taxonomy ] ) ) {
$terms_by_taxonomy[ $term->taxonomy ] = array();
}
$terms_by_taxonomy[ $term->taxonomy ][ $term->slug ] = $term->name;
}
}
return $terms_by_taxonomy;
}
/**
* Save coupon by payment method data in meta
*
* @param Integer $post_id The coupon post ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function process_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$taxonomy_restrictions = ( isset( $_POST['wc_sc_taxonomy_restrictions'] ) ) ? wc_clean( wp_unslash( $_POST['wc_sc_taxonomy_restrictions'] ) ) : array(); // phpcs:ignore
if ( ! empty( $taxonomy_restrictions ) ) {
$taxonomy_restrictions = array_values( $taxonomy_restrictions );
}
if ( $this->is_callable( $coupon, 'update_meta_data' ) && $this->is_callable( $coupon, 'save' ) ) {
$coupon->update_meta_data( 'wc_sc_taxonomy_restrictions', $taxonomy_restrictions );
$coupon->save();
} else {
$this->update_post_meta( $post_id, 'wc_sc_taxonomy_restrictions', $taxonomy_restrictions );
}
}
/**
* Function to validate coupons against taxonomy
*
* @param bool $valid Coupon validity.
* @param WC_Product|null $product Product object.
* @param WC_Coupon|null $coupon Coupon object.
* @param array|null $values Values.
* @return bool $valid
*/
public function validate( $valid = false, $product = null, $coupon = null, $values = null ) {
$backtrace = wp_list_pluck( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ), 'function' ); // phpcs:ignore
// If coupon is already invalid, no need for further checks.
// Ignore this check if the discount type is a non-product-type discount.
if ( true !== $valid && ! in_array( 'handle_non_product_type_coupons', $backtrace, true ) ) {
return $valid;
}
if ( empty( $product ) || empty( $coupon ) ) {
return $valid;
}
$product_ids = array();
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
$product_ids[] = ( is_object( $product ) && is_callable( array( $product, 'get_id' ) ) ) ? $product->get_id() : 0;
$product_ids[] = ( is_object( $product ) && is_callable( array( $product, 'get_parent_id' ) ) ) ? $product->get_parent_id() : 0;
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$product_ids[] = ( ! empty( $product->id ) ) ? $product->id : 0;
$product_ids[] = ( is_object( $product ) && is_callable( array( $product, 'get_parent' ) ) ) ? $product->get_parent() : 0;
}
$product_ids = array_unique( array_filter( $product_ids ) );
if ( ! empty( $coupon_id ) ) {
$taxonomy_restrictions = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_sc_taxonomy_restrictions' ) : $this->get_post_meta( $coupon_id, 'wc_sc_taxonomy_restrictions', true );
if ( ! empty( $taxonomy_restrictions ) ) {
$term_ids = $this->get_restricted_term_ids( array( 'taxonomy_restrictions' => $taxonomy_restrictions ) );
$include_ids = array();
$exclude_ids = array();
if ( isset( $term_ids['include'] ) && is_array( $term_ids['include'] ) ) {
$include_ids = $term_ids['include'];
}
if ( isset( $term_ids['exclude'] ) && is_array( $term_ids['exclude'] ) ) {
$exclude_ids = $term_ids['exclude'];
}
$taxonomies = wp_list_pluck( $taxonomy_restrictions, 'tax' );
$args = array(
'fields' => 'ids',
);
$object_term_ids = wp_get_object_terms( $product_ids, $taxonomies, $args );
$object_term_ids = array_unique( array_filter( $object_term_ids ) );
$taxonomy_found = true;
if ( ! empty( $include_ids ) && is_array( $include_ids ) ) {
$common_term_ids = array_intersect( $include_ids, $object_term_ids );
if ( count( $common_term_ids ) > 0 ) {
$taxonomy_found = true;
} else {
$taxonomy_found = false;
}
}
$exclude_taxonomy_found = false;
if ( ! empty( $exclude_ids ) && is_array( $exclude_ids ) ) {
$common_exclude_term_ids = array_intersect( $exclude_ids, $object_term_ids );
if ( count( $common_exclude_term_ids ) > 0 ) {
$exclude_taxonomy_found = true;
} else {
$exclude_taxonomy_found = false;
}
}
$valid = ( $taxonomy_found && ! $exclude_taxonomy_found ) ? true : false;
}
}
return $valid;
}
/**
* Function to validate non product type coupons against taxonomy restriction
* We need to remove coupon if it does not pass taxonomy validation even for single cart item in case of non product type coupons e.g fixed_cart, smart_coupon since these coupon type require all products in the cart to be valid
*
* @param boolean $valid Coupon validity.
* @param WC_Coupon $coupon Coupon object.
* @param WC_Discounts $discounts Discounts object.
* @throws Exception Validation exception.
* @return boolean $valid Coupon validity
*/
public function handle_non_product_type_coupons( $valid = true, $coupon = null, $discounts = null ) {
// If coupon is already invalid, no need for further checks.
if ( true !== $valid ) {
return $valid;
}
if ( ! is_a( $coupon, 'WC_Coupon' ) ) {
return $valid;
}
if ( $this->is_wc_gte_30() ) {
$coupon_id = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_id' ) ) ) ? $coupon->get_id() : 0;
$discount_type = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
}
if ( ! empty( $coupon_id ) ) {
$taxonomy_restrictions = ( $this->is_callable( $coupon, 'get_meta' ) ) ? $coupon->get_meta( 'wc_sc_taxonomy_restrictions' ) : $this->get_post_meta( $coupon_id, 'wc_sc_taxonomy_restrictions', true );
// If product attributes are not set in coupon, stop further processing and return from here.
if ( empty( $taxonomy_restrictions ) ) {
return $valid;
}
} else {
return $valid;
}
$product_coupon_types = wc_get_product_coupon_types();
// Proceed if it is non product type coupon.
if ( ! in_array( $discount_type, $product_coupon_types, true ) ) {
if ( class_exists( 'WC_Discounts' ) && isset( WC()->cart ) ) {
$wc_cart = WC()->cart;
$wc_discounts = new WC_Discounts( $wc_cart );
$items_to_validate = array();
if ( is_callable( array( $wc_discounts, 'get_items_to_validate' ) ) ) {
$items_to_validate = $wc_discounts->get_items_to_validate();
} elseif ( is_callable( array( $wc_discounts, 'get_items' ) ) ) {
$items_to_validate = $wc_discounts->get_items();
} elseif ( isset( $wc_discounts->items ) && is_array( $wc_discounts->items ) ) {
$items_to_validate = $wc_discounts->items;
}
if ( ! empty( $items_to_validate ) && is_array( $items_to_validate ) ) {
$term_ids = $this->get_restricted_term_ids( array( 'taxonomy_restrictions' => $taxonomy_restrictions ) );
$include_ids = array();
$exclude_ids = array();
if ( isset( $term_ids['include'] ) && is_array( $term_ids['include'] ) ) {
$include_ids = $term_ids['include'];
}
if ( isset( $term_ids['exclude'] ) && is_array( $term_ids['exclude'] ) ) {
$exclude_ids = $term_ids['exclude'];
}
$taxonomies = wp_list_pluck( $taxonomy_restrictions, 'tax' );
$valid_products = array();
$invalid_products = array();
foreach ( $items_to_validate as $item ) {
$cart_item = clone $item; // Clone the item so changes to wc_discounts item do not affect the originals.
$item_product = isset( $cart_item->product ) ? $cart_item->product : null;
$item_object = isset( $cart_item->object ) ? $cart_item->object : null;
if ( ! is_null( $item_product ) && ! is_null( $item_object ) ) {
if ( $coupon->is_valid_for_product( $item_product, $item_object ) ) {
$valid_products[] = $item_product;
} else {
$invalid_products[] = $item_product;
}
}
}
// If cart does not have any valid product then throw Exception.
if ( 0 === count( $valid_products ) ) {
$error_message = __( 'Sorry, this coupon is not applicable to selected products.', 'woocommerce-smart-coupons' );
$error_code = defined( 'E_WC_COUPON_NOT_APPLICABLE' ) ? E_WC_COUPON_NOT_APPLICABLE : 0;
throw new Exception( $error_message, $error_code );
} elseif ( count( $invalid_products ) > 0 && ! empty( $exclude_ids ) ) {
$excluded_products = array();
foreach ( $invalid_products as $invalid_product ) {
$product_ids = array();
$product_ids[] = ( is_object( $invalid_product ) && is_callable( array( $invalid_product, 'get_id' ) ) ) ? $invalid_product->get_id() : 0;
$product_ids[] = ( is_object( $invalid_product ) && is_callable( array( $invalid_product, 'get_parent_id' ) ) ) ? $invalid_product->get_parent_id() : 0;
$product_name = ( is_object( $invalid_product ) && is_callable( array( $invalid_product, 'get_name' ) ) ) ? $invalid_product->get_name() : '';
$args = array(
'fields' => 'ids',
);
$object_term_ids = wp_get_object_terms( $product_ids, $taxonomies, $args );
$object_term_ids = array_unique( array_filter( $object_term_ids ) );
if ( ! empty( $object_term_ids ) && is_array( $object_term_ids ) ) {
$common_exclude_term_ids = array_intersect( $exclude_ids, $object_term_ids );
if ( count( $common_exclude_term_ids ) > 0 ) {
$excluded_products[] = $product_name;
}
}
}
if ( count( $excluded_products ) > 0 ) {
// If cart contains any excluded product and it is being excluded from our excluded product attributes then throw Exception.
/* translators: 1. Singular/plural label for product(s) 2. Excluded product names */
$error_message = sprintf( __( 'Sorry, this coupon is not applicable to the %1$s: %2$s.', 'woocommerce-smart-coupons' ), _n( 'product', 'products', count( $excluded_products ), 'woocommerce-smart-coupons' ), implode( ', ', $excluded_products ) );
$error_code = defined( 'E_WC_COUPON_EXCLUDED_PRODUCTS' ) ? E_WC_COUPON_EXCLUDED_PRODUCTS : 0;
throw new Exception( $error_message, $error_code );
}
}
}
}
}
return $valid;
}
/**
* Get restricted term ids
*
* @param array $args Arguments.
* @return array
*/
public function get_restricted_term_ids( $args = array() ) {
global $wp_taxonomies;
$term_ids = array();
$taxonomy_restrictions = ( ! empty( $args['taxonomy_restrictions'] ) ) ? $args['taxonomy_restrictions'] : array();
if ( ! empty( $taxonomy_restrictions ) && is_array( $taxonomy_restrictions ) ) {
$include_ids = array();
$exclude_ids = array();
foreach ( $taxonomy_restrictions as $taxonomy_restriction ) {
$taxonomy = ( ! empty( $taxonomy_restriction['tax'] ) ) ? $taxonomy_restriction['tax'] : '';
$operator = ( ! empty( $taxonomy_restriction['op'] ) ) ? $taxonomy_restriction['op'] : '';
$value = ( ! empty( $taxonomy_restriction['val'] ) ) ? $taxonomy_restriction['val'] : array();
if ( ! empty( $taxonomy ) && ! empty( $operator ) && ! empty( $value ) ) {
$args = array(
'taxonomy' => $taxonomy,
'hide_empty' => false,
'fields' => 'ids',
'slug' => $value,
);
$found_ids = get_terms( $args );
$found_ids = array_unique( array_filter( $found_ids ) );
if ( ! empty( $found_ids ) ) {
switch ( $operator ) {
case 'incl':
$include_ids = array_merge( $include_ids, $found_ids );
break;
case 'excl':
$exclude_ids = array_merge( $exclude_ids, $found_ids );
break;
}
}
}
}
if ( ! empty( $include_ids ) ) {
$term_ids['include'] = array_unique( array_filter( $include_ids ) );
}
if ( ! empty( $exclude_ids ) ) {
$term_ids['exclude'] = array_unique( array_filter( $exclude_ids ) );
}
}
return $term_ids;
}
/**
* Function to copy taxonomy restriction meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_taxonomy_meta( $args = array() ) {
// Copy meta data to new coupon.
$this->copy_coupon_meta_data(
$args,
array( 'wc_sc_taxonomy_restrictions' )
);
}
/**
* Make meta data of wc_sc_taxonomy_restrictions protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected = false, $meta_key = '', $meta_type = '' ) {
if ( 'wc_sc_taxonomy_restrictions' === $meta_key ) {
return true;
}
return $protected;
}
/**
* Add taxonomy restriction meta with value in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array Modified data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
if ( isset( $post['wc_sc_taxonomy_restrictions'] ) && is_array( $post['wc_sc_taxonomy_restrictions'] ) && ! empty( $post['wc_sc_taxonomy_restrictions'] ) ) {
$data['wc_sc_taxonomy_restrictions'] = maybe_serialize( array_values( $post['wc_sc_taxonomy_restrictions'] ) );
}
return $data;
}
/**
* Post meta defaults for product quantity restriction meta
*
* @param array $defaults Existing postmeta defaults.
* @return array
*/
public function postmeta_defaults( $defaults = array() ) {
return array_merge( $defaults, array( 'wc_sc_taxonomy_restrictions' => '' ) );
}
/**
* Process coupon meta value for import
*
* @param mixed $meta_value The meta value.
* @param array $args Additional Arguments.
* @return mixed $meta_value
*/
public function process_coupon_meta_value_for_import( $meta_value = null, $args = array() ) {
return ( ! empty( $args['meta_key'] ) && 'wc_sc_taxonomy_restrictions' === $args['meta_key'] && ! empty( $args['postmeta'] ) && ! empty( $args['postmeta']['wc_sc_taxonomy_restrictions'] ) ) ? $args['postmeta']['wc_sc_taxonomy_restrictions'] : $meta_value;
}
/**
* Add wc_sc_taxonomy_restrictions meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$product_wc_sc_taxonomy_restrictions = array(
'wc_sc_taxonomy_restrictions' => __( 'Taxonomy based restrictions', 'woocommerce-smart-coupons' ),
);
return array_merge( $headers, $product_wc_sc_taxonomy_restrictions );
}
}
}
WC_SC_Coupons_By_Taxonomy::get_instance();

View File

@@ -0,0 +1,547 @@
<?php
/**
* Class to handle feature Coupons By User Role
*
* @author StoreApps
* @category Admin
* @package wocommerce-smart-coupons/includes
* @version 2.1.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Coupons_By_User_Role' ) ) {
/**
* Class WC_SC_Coupons_By_User_Role
*/
class WC_SC_Coupons_By_User_Role {
/**
* Variable to hold instance of this class
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
public function __construct() {
add_action( 'woocommerce_coupon_options_usage_restriction', array( $this, 'usage_restriction' ), 10, 2 );
add_action( 'woocommerce_coupon_options_save', array( $this, 'process_meta' ), 10, 2 );
add_filter( 'woocommerce_coupon_is_valid', array( $this, 'validate' ), 11, 3 );
add_action( 'woocommerce_after_checkout_validation', array( $this, 'validate_after_checkout' ), 99, 2 );
add_filter( 'wc_smart_coupons_export_headers', array( $this, 'export_headers' ) );
add_filter( 'wc_sc_export_coupon_meta', array( $this, 'export_coupon_meta_data' ), 10, 2 );
add_filter( 'smart_coupons_parser_postmeta_defaults', array( $this, 'postmeta_defaults' ) );
add_filter( 'sc_generate_coupon_meta', array( $this, 'generate_coupon_meta' ), 10, 2 );
add_filter( 'wc_sc_process_coupon_meta_value_for_import', array( $this, 'process_coupon_meta_value_for_import' ), 10, 2 );
add_filter( 'is_protected_meta', array( $this, 'make_action_meta_protected' ), 10, 3 );
add_action( 'wc_sc_new_coupon_generated', array( $this, 'copy_coupon_user_role_meta' ) );
}
/**
* Get single instance of this class
*
* @return this class Singleton object of this class
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name = '', $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Display field for coupon by user role
*
* @param integer $coupon_id The coupon id.
* @param WC_Coupon $coupon The coupon object.
*/
public function usage_restriction( $coupon_id = 0, $coupon = null ) {
$user_role_ids = array();
$exclude_user_role_ids = array();
if ( ! empty( $coupon_id ) ) {
if ( ! is_a( $coupon, 'WC_Coupon' ) ) {
$coupon = new WC_Coupon( $coupon_id );
}
$is_callable_coupon_get_meta = $this->is_callable( $coupon, 'get_meta' );
$user_role_ids = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'wc_sc_user_role_ids' ) : get_post_meta( $coupon_id, 'wc_sc_user_role_ids', true );
if ( empty( $user_role_ids ) || ! is_array( $user_role_ids ) ) {
$user_role_ids = array();
}
$exclude_user_role_ids = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'wc_sc_exclude_user_role_ids' ) : get_post_meta( $coupon_id, 'wc_sc_exclude_user_role_ids', true );
if ( empty( $exclude_user_role_ids ) || ! is_array( $exclude_user_role_ids ) ) {
$exclude_user_role_ids = array();
}
}
$available_user_roles = $this->get_available_user_roles();
?>
<div class="options_group smart-coupons-field">
<p class="form-field">
<label for="wc_sc_user_role_ids"><?php echo esc_html__( 'Allowed user roles', 'woocommerce-smart-coupons' ); ?></label>
<select id="wc_sc_user_role_ids" name="wc_sc_user_role_ids[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No user roles', 'woocommerce-smart-coupons' ); ?>">
<?php
if ( ! empty( $available_user_roles ) && is_array( $available_user_roles ) ) {
foreach ( $available_user_roles as $role_id => $role ) {
$role_name = translate_user_role( $role['name'] );
echo '<option value="' . esc_attr( $role_id ) . '"' . esc_attr( selected( in_array( $role_id, $user_role_ids, true ), true, false ) ) . '>' . esc_html( $role_name ) . '</option>';
}
}
?>
</select>
<?php
$tooltip_text = esc_html__( 'Role of the users for whom this coupon is valid. Keep empty if you want this coupon to be valid for users with any role.', 'woocommerce-smart-coupons' );
echo wc_help_tip( $tooltip_text ); // phpcs:ignore
?>
</p>
<p class="form-field">
<label for="wc_sc_exclude_user_role_ids"><?php echo esc_html__( 'Exclude user roles', 'woocommerce-smart-coupons' ); ?></label>
<select id="wc_sc_exclude_user_role_ids" name="wc_sc_exclude_user_role_ids[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No user roles', 'woocommerce-smart-coupons' ); ?>">
<?php
if ( ! empty( $available_user_roles ) && is_array( $available_user_roles ) ) {
foreach ( $available_user_roles as $role_id => $role ) {
$role_name = translate_user_role( $role['name'] );
echo '<option value="' . esc_attr( $role_id ) . '"' . esc_attr( selected( in_array( $role_id, $exclude_user_role_ids, true ), true, false ) ) . '>' . esc_html( $role_name ) . '</option>';
}
}
?>
</select>
<?php
$tooltip_text = esc_html__( 'Role of the users for whom this coupon is not valid. Keep empty if you want this coupon to be valid for users with any role.', 'woocommerce-smart-coupons' );
echo wc_help_tip( $tooltip_text ); // phpcs:ignore
?>
</p>
</div>
<?php
}
/**
* Save coupon by user role data in meta
*
* @param Integer $post_id The coupon post ID.
* @param WC_Coupon $coupon The coupon object.
*/
public function process_meta( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $coupon );
$user_role_ids = ( isset( $_POST['wc_sc_user_role_ids'] ) ) ? wc_clean( wp_unslash( $_POST['wc_sc_user_role_ids'] ) ) : array(); // phpcs:ignore
$exclude_user_role_ids = ( isset( $_POST['wc_sc_exclude_user_role_ids'] ) ) ? wc_clean( wp_unslash( $_POST['wc_sc_exclude_user_role_ids'] ) ) : array(); // phpcs:ignore
if ( $this->is_callable( $coupon, 'update_meta_data' ) && $this->is_callable( $coupon, 'save' ) ) {
$coupon->update_meta_data( 'wc_sc_user_role_ids', $user_role_ids );
$coupon->update_meta_data( 'wc_sc_exclude_user_role_ids', $exclude_user_role_ids );
$coupon->save();
} else {
update_post_meta( $post_id, 'wc_sc_user_role_ids', $user_role_ids );
update_post_meta( $post_id, 'wc_sc_exclude_user_role_ids', $exclude_user_role_ids );
}
}
/**
* Validate the coupon based on user role
*
* @param boolean $valid Is valid or not.
* @param WC_Coupon $coupon The coupon object.
* @param WC_Discounts $discounts The discount object.
*
* @throws Exception If the coupon is invalid.
* @return boolean Is valid or not
*/
public function validate( $valid = false, $coupon = object, $discounts = null ) {
// If coupon is invalid already, no need for further checks.
if ( false === $valid ) {
return $valid;
}
$coupon_id = ( $this->is_wc_gte_30() ) ? $coupon->get_id() : $coupon->id;
if ( ! is_a( $coupon, 'WC_Coupon' ) ) {
$coupon = new WC_Coupon( $coupon_id );
}
if ( $this->is_callable( $coupon, 'get_meta' ) ) {
$user_role_ids = $coupon->get_meta( 'wc_sc_user_role_ids' );
$exclude_user_role_ids = $coupon->get_meta( 'wc_sc_exclude_user_role_ids' );
} else {
$user_role_ids = get_post_meta( $coupon_id, 'wc_sc_user_role_ids', true );
$exclude_user_role_ids = get_post_meta( $coupon_id, 'wc_sc_exclude_user_role_ids', true );
}
$current_user = wp_get_current_user();
$post_action = ( ! empty( $_POST['action'] ) ) ? wc_clean( wp_unslash( $_POST['action'] ) ) : ''; // phpcs:ignore
if ( is_admin() && wp_doing_ajax() && 'woocommerce_add_coupon_discount' === $post_action ) { // This condition will allow the addition of coupon from admin side, in the order even if the user role is not matching.
return true;
}
if ( is_array( $user_role_ids ) && ! empty( $user_role_ids ) ) {
// Check if current user's role is allowed.
if ( ! array_intersect( $current_user->roles, $user_role_ids ) ) {
throw new Exception( __( 'This coupon is not valid for you.', 'woocommerce-smart-coupons' ) );
}
}
if ( is_array( $exclude_user_role_ids ) && ! empty( $exclude_user_role_ids ) ) {
// Check if current user's role is excluded.
if ( array_intersect( $current_user->roles, $exclude_user_role_ids ) ) {
throw new Exception( __( 'This coupon is not valid for you.', 'woocommerce-smart-coupons' ) );
}
}
return $valid;
}
/**
* Add meta in export headers
*
* @param array $headers Existing headers.
* @return array
*/
public function export_headers( $headers = array() ) {
$headers['wc_sc_user_role_ids'] = __( 'User Role', 'woocommerce-smart-coupons' );
$headers['wc_sc_exclude_user_role_ids'] = __( 'Exclude User Role', 'woocommerce-smart-coupons' );
return $headers;
}
/**
* Function to handle coupon meta data during export of existing coupons
*
* @param mixed $meta_value The meta value.
* @param array $args Additional arguments.
* @return string Processed meta value
*/
public function export_coupon_meta_data( $meta_value = '', $args = array() ) {
if ( ! empty( $args['meta_key'] ) ) {
if ( 'wc_sc_user_role_ids' === $args['meta_key'] ) {
if ( isset( $args['meta_value'] ) && ! empty( $args['meta_value'] ) ) {
$user_role_ids = maybe_unserialize( stripslashes( $args['meta_value'] ) );
if ( is_array( $user_role_ids ) && ! empty( $user_role_ids ) ) {
$user_role_names = $this->get_user_role_names_by_ids( $user_role_ids );
if ( is_array( $user_role_names ) && ! empty( $user_role_names ) ) {
$meta_value = implode( '|', wc_clean( wp_unslash( $user_role_names ) ) ); // Replace user role ids with their respective role name.
}
}
}
} elseif ( 'wc_sc_exclude_user_role_ids' === $args['meta_key'] ) {
if ( isset( $args['meta_value'] ) && ! empty( $args['meta_value'] ) ) {
$exclude_user_role_ids = maybe_unserialize( stripslashes( $args['meta_value'] ) );
if ( is_array( $exclude_user_role_ids ) && ! empty( $exclude_user_role_ids ) ) {
$exclude_user_role_names = $this->get_user_role_names_by_ids( $exclude_user_role_ids );
if ( is_array( $exclude_user_role_names ) && ! empty( $exclude_user_role_names ) ) {
$meta_value = implode( '|', wc_clean( wp_unslash( $exclude_user_role_names ) ) ); // Replace user role ids with their respective role name.
}
}
}
}
}
return $meta_value;
}
/**
* Post meta defaults for user role ids meta
*
* @param array $defaults Existing postmeta defaults.
* @return array
*/
public function postmeta_defaults( $defaults = array() ) {
$defaults['wc_sc_user_role_ids'] = '';
$defaults['wc_sc_exclude_user_role_ids'] = '';
return $defaults;
}
/**
* Add user role's meta with value in coupon meta
*
* @param array $data The row data.
* @param array $post The POST values.
* @return array Modified data
*/
public function generate_coupon_meta( $data = array(), $post = array() ) {
$user_role_names = '';
$exclude_user_role_names = '';
if ( ! empty( $post['wc_sc_user_role_ids'] ) && is_array( $post['wc_sc_user_role_ids'] ) ) {
$user_role_names = $this->get_user_role_names_by_ids( $post['wc_sc_user_role_ids'] );
if ( is_array( $user_role_names ) && ! empty( $user_role_names ) ) {
$user_role_names = implode( '|', wc_clean( wp_unslash( $user_role_names ) ) );
}
}
if ( ! empty( $post['wc_sc_exclude_user_role_ids'] ) && is_array( $post['wc_sc_exclude_user_role_ids'] ) ) {
$exclude_user_role_names = $this->get_user_role_names_by_ids( $post['wc_sc_exclude_user_role_ids'] );
if ( is_array( $exclude_user_role_names ) && ! empty( $exclude_user_role_names ) ) {
$exclude_user_role_names = implode( '|', wc_clean( wp_unslash( $exclude_user_role_names ) ) );
}
}
$data['wc_sc_user_role_ids'] = $user_role_names; // Replace user role ids with their respective role name.
$data['wc_sc_exclude_user_role_ids'] = $exclude_user_role_names; // Replace user role ids with their respective role name.
return $data;
}
/**
* Function to get user role titles for given user role ids
*
* @param array $user_role_ids ids of user roles.
* @return array $user_role_names titles of user roles
*/
public function get_user_role_names_by_ids( $user_role_ids = array() ) {
$user_role_names = array();
if ( is_array( $user_role_ids ) && ! empty( $user_role_ids ) ) {
$available_user_roles = $this->get_available_user_roles();
foreach ( $user_role_ids as $index => $user_role_id ) {
$user_role = ( isset( $available_user_roles[ $user_role_id ] ) && ! empty( $available_user_roles[ $user_role_id ] ) ) ? $available_user_roles[ $user_role_id ] : '';
if ( is_array( $user_role ) && ! empty( $user_role ) ) {
$user_role_name = ! empty( $user_role['name'] ) ? $user_role['name'] : '';
if ( ! empty( $user_role_name ) ) {
$user_role_names[ $index ] = $user_role_name; // Replace user role id with it's repective name.
} else {
$user_role_names[ $index ] = $user_role_id; // In case of empty user role name replace it with role id.
}
}
}
}
return $user_role_names;
}
/**
* Process coupon meta value for import
*
* @param mixed $meta_value The meta value.
* @param array $args Additional Arguments.
* @return mixed $meta_value
*/
public function process_coupon_meta_value_for_import( $meta_value = null, $args = array() ) {
if ( ! empty( $args['meta_key'] ) ) {
$available_user_roles = $this->get_available_user_roles();
if ( 'wc_sc_user_role_ids' === $args['meta_key'] ) {
$meta_value = ( ! empty( $args['postmeta']['wc_sc_user_role_ids'] ) ) ? explode( '|', wc_clean( wp_unslash( $args['postmeta']['wc_sc_user_role_ids'] ) ) ) : array();
if ( is_array( $meta_value ) && ! empty( $meta_value ) ) {
if ( is_array( $available_user_roles ) && ! empty( $available_user_roles ) ) {
foreach ( $meta_value as $index => $user_role_name ) {
foreach ( $available_user_roles as $role_id => $user_role ) {
$role_name = isset( $user_role['name'] ) ? $user_role['name'] : '';
if ( $role_name === $user_role_name ) {
$meta_value[ $index ] = $role_id; // Replace user role title with it's repective id.
}
}
}
}
}
} elseif ( 'wc_sc_exclude_user_role_ids' === $args['meta_key'] ) {
$meta_value = ( ! empty( $args['postmeta']['wc_sc_exclude_user_role_ids'] ) ) ? explode( '|', wc_clean( wp_unslash( $args['postmeta']['wc_sc_exclude_user_role_ids'] ) ) ) : array();
if ( is_array( $meta_value ) && ! empty( $meta_value ) ) {
if ( is_array( $available_user_roles ) && ! empty( $available_user_roles ) ) {
foreach ( $meta_value as $index => $user_role_name ) {
foreach ( $available_user_roles as $role_id => $user_role ) {
$role_name = isset( $user_role['name'] ) ? $user_role['name'] : '';
if ( $role_name === $user_role_name ) {
$meta_value[ $index ] = $role_id; // Replace user role title with it's repective id.
}
}
}
}
}
}
}
return $meta_value;
}
/**
* Make meta data of user role ids protected
*
* @param bool $protected Is protected.
* @param string $meta_key The meta key.
* @param string $meta_type The meta type.
* @return bool $protected
*/
public function make_action_meta_protected( $protected = false, $meta_key = '', $meta_type = '' ) {
if ( in_array( $meta_key, array( 'wc_sc_user_role_ids', 'wc_sc_exclude_user_role_ids' ), true ) ) {
return true;
}
return $protected;
}
/**
* Function to get available user roles which current user use.
*
* @return array $available_user_roles Available user roles
*/
public function get_available_user_roles() {
$available_user_roles = array();
if ( ! function_exists( 'get_editable_roles' ) ) {
require_once ABSPATH . 'wp-admin/includes/user.php';
}
if ( function_exists( 'get_editable_roles' ) ) {
$available_user_roles = get_editable_roles();
}
return $available_user_roles;
}
/**
* Function to copy user role restriction meta in newly generated coupon
*
* @param array $args The arguments.
*/
public function copy_coupon_user_role_meta( $args = array() ) {
// Copy meta data to new coupon.
$this->copy_coupon_meta_data(
$args,
array( 'wc_sc_user_role_ids', 'wc_sc_exclude_user_role_ids' )
);
}
/**
* Validate user role after checkout.
*
* @param array $posted Post data.
* @param WP_Error $errors Validation errors.
* @return void
*/
public function validate_after_checkout( $posted = array(), $errors = object ) {
$current_user_id = get_current_user_id();
if ( ! empty( $current_user_id ) ) {
return;
}
$billing_email = ! empty( $posted['billing_email'] ) ? $posted['billing_email'] : '';
if ( empty( $posted['billing_email'] ) ) {
return;
}
$cart = ( function_exists( 'WC' ) && isset( WC()->cart ) ) ? WC()->cart : null;
if ( is_a( $cart, 'WC_Cart' ) ) {
$is_cart_empty = is_callable( array( $cart, 'is_empty' ) ) && $cart->is_empty();
if ( false === $is_cart_empty ) {
$applied_coupons = ( is_callable( array( $cart, 'get_applied_coupons' ) ) ) ? $cart->get_applied_coupons() : array();
if ( ! empty( $applied_coupons ) ) {
foreach ( $applied_coupons as $code ) {
$coupon = new WC_Coupon( $code );
if ( ! is_object( $coupon ) ) {
continue;
}
if ( is_callable( array( $coupon, 'get_meta' ) ) ) {
$user_role_ids = $coupon->get_meta( 'wc_sc_user_role_ids' );
$exclude_user_role_ids = $coupon->get_meta( 'wc_sc_exclude_user_role_ids' );
} else {
if ( is_callable( array( $coupon, 'get_id' ) ) ) {
$coupon_id = $coupon->get_id();
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
}
if ( empty( $coupon_id ) ) {
continue;
}
$user_role_ids = get_post_meta( $coupon_id, 'wc_sc_user_role_ids', true );
$exclude_user_role_ids = get_post_meta( $coupon_id, 'wc_sc_exclude_user_role_ids', true );
}
if ( empty( $exclude_user_role_ids ) && empty( $user_role_ids ) ) {
continue;
}
$current_user = get_user_by( 'email', $billing_email );
$current_user_roles = ! empty( $current_user->roles ) ? $current_user->roles : array();
$is_message = is_callable( array( $coupon, 'add_coupon_message' ) );
$is_remove = is_callable( array( $cart, 'remove_coupon' ) );
if ( is_array( $user_role_ids ) && ! empty( $user_role_ids ) ) {
// Check if current user's role is allowed.
if ( ! array_intersect( $current_user_roles, $user_role_ids ) ) {
if ( true === $is_message ) {
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED );
}
if ( true === $is_remove ) {
$cart->remove_coupon( $code );
}
}
}
if ( is_array( $exclude_user_role_ids ) && ! empty( $exclude_user_role_ids ) ) {
// Check if current user's role is excluded.
if ( array_intersect( $current_user_roles, $exclude_user_role_ids ) ) {
if ( true === $is_message ) {
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED );
}
if ( true === $is_remove ) {
$cart->remove_coupon( $code );
}
}
}
}
}
}
}
}
}
}
WC_SC_Coupons_By_User_Role::get_instance();

View File

@@ -0,0 +1,347 @@
<?php
/**
* Maintain Global Coupon's record
*
* @author StoreApps
* @since 3.3.0
* @version 1.9.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Global_Coupons' ) ) {
/**
* Class for handling global coupons
*/
class WC_SC_Global_Coupons {
/**
* Variable to hold instance of WC_SC_Global_Coupons
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'admin_init', array( $this, 'set_global_coupons' ) );
add_action( 'woocommerce_coupon_options_save', array( $this, 'update_global_coupons' ), 99, 2 );
add_action( 'deleted_post', array( $this, 'sc_delete_global_coupons' ) );
add_action( 'trashed_post', array( $this, 'sc_delete_global_coupons' ) );
add_action( 'untrashed_post', array( $this, 'sc_untrash_global_coupons' ) );
add_action( 'future_to_publish', array( $this, 'future_to_publish_global_coupons' ) );
}
/**
* Get single instance of WC_SC_Global_Coupons
*
* @return WC_SC_Global_Coupons Singleton object of WC_SC_Global_Coupons
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name = '', $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Set global coupons in options table for faster fetching
*/
public function set_global_coupons() {
global $wpdb;
$global_coupon_option_name = 'sc_display_global_coupons';
$global_coupons = $this->sc_get_option( $global_coupon_option_name );
$current_sc_version = get_option( 'sa_sc_db_version', '' ); // code for updating the db - for autoload related fix.
if ( false === $global_coupons ) {
$wpdb->query( $wpdb->prepare( 'SET SESSION group_concat_max_len=%d', 999999 ) ); // phpcs:ignore
$wpdb->delete( $wpdb->prefix . 'options', array( 'option_name' => $global_coupon_option_name ) ); // WPCS: cache ok, db call ok.
$wpdb->query( // phpcs:ignore
$wpdb->prepare(
"REPLACE INTO {$wpdb->prefix}options (option_name, option_value, autoload)
SELECT %s,
IFNULL(GROUP_CONCAT(p.id SEPARATOR ','), ''),
%s
FROM {$wpdb->prefix}posts AS p
JOIN {$wpdb->prefix}postmeta AS pm
ON(pm.post_id = p.ID
AND p.post_type = %s
AND p.post_status = %s
AND pm.meta_key = %s
AND pm.meta_value = %s)
",
$global_coupon_option_name,
'no',
'shop_coupon',
'publish',
'sc_is_visible_storewide',
'yes'
)
);
if ( ! empty( $this->sc_get_option( $global_coupon_option_name ) ) ) {
$wpdb->query( // phpcs:ignore
$wpdb->prepare(
"UPDATE {$wpdb->prefix}options
SET option_value = (SELECT IFNULL(GROUP_CONCAT(DISTINCT pm.post_id SEPARATOR ','), '')
FROM {$wpdb->prefix}postmeta AS pm
WHERE ( ( pm.meta_key = %s AND CAST(pm.meta_value AS CHAR) = %s )
OR NOT EXISTS( SELECT 1 FROM {$wpdb->prefix}postmeta AS pm1 WHERE pm1.meta_key = %s AND pm.post_id = pm1.post_id ) )
AND FIND_IN_SET(pm.post_id, (SELECT option_value FROM (SELECT option_value FROM {$wpdb->prefix}options WHERE option_name = %s) as temp )) > 0 )
WHERE option_name = %s",
'customer_email',
'a:0:{}',
'customer_email',
$global_coupon_option_name,
$global_coupon_option_name
)
);
if ( ! empty( $this->sc_get_option( $global_coupon_option_name ) ) ) {
$wpdb->query( // phpcs:ignore
$wpdb->prepare(
"UPDATE {$wpdb->prefix}options
SET option_value = (SELECT IFNULL(GROUP_CONCAT(post_id SEPARATOR ','), '')
FROM {$wpdb->prefix}postmeta
WHERE meta_key = %s
AND CAST(meta_value AS CHAR) != %s
AND FIND_IN_SET(post_id, (SELECT option_value FROM (SELECT option_value FROM {$wpdb->prefix}options WHERE option_name = %s) as temp )) > 0 )
WHERE option_name = %s",
'auto_generate_coupon',
'yes',
$global_coupon_option_name,
$global_coupon_option_name
)
);
if ( ! empty( $this->sc_get_option( $global_coupon_option_name ) ) ) {
$wpdb->query( // phpcs:ignore
$wpdb->prepare(
"UPDATE {$wpdb->prefix}options
SET option_value = (SELECT IFNULL(GROUP_CONCAT(post_id SEPARATOR ','), '')
FROM {$wpdb->prefix}postmeta
WHERE meta_key = %s
AND CAST(meta_value AS CHAR) != %s
AND FIND_IN_SET(post_id, (SELECT option_value FROM (SELECT option_value FROM {$wpdb->prefix}options WHERE option_name = %s) as temp )) > 0 )
WHERE option_name = %s",
'discount_type',
'smart_coupon',
$global_coupon_option_name,
$global_coupon_option_name
)
);
if ( ! empty( $this->sc_get_option( $global_coupon_option_name ) ) ) {
$wpdb->query( // phpcs:ignore
$wpdb->prepare(
"UPDATE {$wpdb->prefix}options
SET option_value = (SELECT IFNULL(GROUP_CONCAT(DISTINCT pm_expiry_date.post_id SEPARATOR ','), '')
FROM {$wpdb->prefix}postmeta AS pm_expiry_date
JOIN {$wpdb->prefix}postmeta AS pm_expiry_time
on ( pm_expiry_time.post_id = pm_expiry_date.post_id
AND pm_expiry_date.meta_key = %s
AND pm_expiry_time.meta_key = %s
)
WHERE ( (pm_expiry_date.meta_value IS NULL OR pm_expiry_date.meta_value = '')
OR ( IFNULL(pm_expiry_date.meta_value, 0) + IFNULL(pm_expiry_time.meta_value, 0) ) > %d )
AND FIND_IN_SET(pm_expiry_date.post_id, (SELECT option_value FROM (SELECT option_value FROM {$wpdb->prefix}options WHERE option_name = %s) as temp )) > 0 )
WHERE option_name = %s",
'date_expires',
'wc_sc_expiry_time',
time(),
$global_coupon_option_name,
$global_coupon_option_name
)
);
$global_coupons = $this->sc_get_option( $global_coupon_option_name );
}
}
}
}
}
if ( ( empty( $current_sc_version ) || version_compare( $current_sc_version, '3.3.6', '<' ) ) && ! empty( $this->sc_get_option( $global_coupon_option_name ) ) ) {
$wpdb->query( // phpcs:ignore
$wpdb->prepare(
"UPDATE {$wpdb->prefix}options
SET autoload = %s
WHERE option_name = %s",
'no',
$global_coupon_option_name
)
);
$current_sc_version = '3.3.6';
update_option( 'sa_sc_db_version', $current_sc_version, 'no' );
}
}
/**
* Function to update list of global coupons
*
* @param int $post_id The post id.
* @param string $action Action.
* @param WC_Coupon $coupon The coupon object.
*/
public function sc_update_global_coupons( $post_id, $action = 'add', $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
if ( 'shop_coupon' !== $this->get_post_type( $post_id ) ) {
return;
}
$coupon = new WC_Coupon( $post_id );
$coupon_status = ( $this->is_wc_greater_than( '6.1.2' ) && $this->is_callable( $coupon, 'get_status' ) ) ? $coupon->get_status() : get_post_status( $post_id );
if ( $this->is_callable( $coupon, 'get_meta' ) ) {
$customer_email = $coupon->get_email_restrictions();
$sc_is_visible_storewide = $coupon->get_meta( 'sc_is_visible_storewide' );
$auto_generate_coupon = $coupon->get_meta( 'auto_generate_coupon' );
$discount_type = $coupon->get_discount_type();
} else {
$coupon_meta = get_post_meta( $post_id );
$customer_email = ( ! empty( $coupon_meta['customer_email'] ) ) ? $coupon_meta['customer_email'][0] : '';
$sc_is_visible_storewide = ( ! empty( $coupon_meta['sc_is_visible_storewide'] ) ) ? $coupon_meta['sc_is_visible_storewide'][0] : '';
$auto_generate_coupon = ( ! empty( $coupon_meta['auto_generate_coupon'] ) ) ? $coupon_meta['auto_generate_coupon'][0] : '';
$discount_type = ( ! empty( $coupon_meta['discount_type'] ) ) ? $coupon_meta['discount_type'][0] : '';
}
$global_coupons_list = get_option( 'sc_display_global_coupons' );
$global_coupons = ( ! empty( $global_coupons_list ) ) ? explode( ',', $global_coupons_list ) : array();
$key = array_search( (string) $post_id, $global_coupons, true );
if ( ( 'publish' === $coupon_status
&& ( empty( $customer_email ) || serialize( array() ) === $customer_email ) // phpcs:ignore
&& ( ! empty( $sc_is_visible_storewide ) && 'yes' === $sc_is_visible_storewide )
&& ( ! empty( $auto_generate_coupon ) && 'yes' !== $auto_generate_coupon )
&& ( ! empty( $discount_type ) && 'smart_coupon' !== $discount_type ) )
|| ( 'trash' === $coupon_status && 'delete' === $action ) ) {
if ( 'add' === $action && false === $key ) {
$global_coupons[] = $post_id;
} elseif ( 'delete' === $action && false !== $key ) {
unset( $global_coupons[ $key ] );
}
} else {
if ( false !== $key ) {
unset( $global_coupons[ $key ] );
}
}
update_option( 'sc_display_global_coupons', implode( ',', array_unique( $global_coupons ) ), 'no' );
}
/**
* Function to update list of global coupons on trash / delete coupon
*
* @param int $post_id The post id.
*/
public function sc_delete_global_coupons( $post_id ) {
if ( empty( $post_id ) ) {
return;
}
if ( 'shop_coupon' !== $this->get_post_type( $post_id ) ) {
return;
}
$this->sc_update_global_coupons( $post_id, 'delete' );
}
/**
* Function to update list of global coupons on untrash coupon
*
* @param int $post_id The post id.
*/
public function sc_untrash_global_coupons( $post_id ) {
if ( empty( $post_id ) ) {
return;
}
if ( 'shop_coupon' !== $this->get_post_type( $post_id ) ) {
return;
}
$this->sc_update_global_coupons( $post_id );
}
/**
* Update global coupons data for sheduled coupons
*
* @param WP_Post $post The post object.
*/
public function future_to_publish_global_coupons( $post = null ) {
$post_id = ( ! empty( $post->ID ) ) ? $post->ID : 0;
if ( empty( $post ) || empty( $post_id ) ) {
return;
}
if ( 'shop_coupon' !== $post->post_type ) {
return;
}
$this->sc_update_global_coupons( $post_id );
}
/**
* Update global coupons on saving coupon
*
* @param int $post_id The post id.
* @param WC_Coupon $coupon The coupon object.
*/
public function update_global_coupons( $post_id = 0, $coupon = null ) {
if ( empty( $post_id ) ) {
return;
}
if ( is_null( $coupon ) || ! is_a( $coupon, 'WC_Coupon' ) ) {
$coupon = new WC_Coupon( $post_id );
}
$this->sc_update_global_coupons( $post_id, 'add', $coupon );
}
}
}
WC_SC_Global_Coupons::get_instance();

View File

@@ -0,0 +1,602 @@
<?php
/**
* Smart Coupons fields in orders
*
* @author StoreApps
* @since 3.3.0
* @version 1.8.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Order_Fields' ) ) {
/**
* Class for handling Smart Coupons' field in orders
*/
class WC_SC_Order_Fields {
/**
* Variable to hold instance of WC_SC_Order_Fields
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_admin_order_totals_after_tax', array( $this, 'admin_order_totals_add_smart_coupons_discount_details' ) );
add_filter( 'woocommerce_get_order_item_totals', array( $this, 'add_smart_coupons_discount_details' ), 10, 3 );
add_action( 'wp_loaded', array( $this, 'order_fields_hooks' ) );
add_filter( 'woocommerce_cart_totals_coupon_label', array( $this, 'cart_totals_smart_coupons_label' ), 10, 2 );
add_filter( 'woocommerce_cart_totals_order_total_html', array( $this, 'cart_totals_order_total_html' ), 99 );
add_filter( 'woocommerce_get_formatted_order_total', array( $this, 'get_formatted_order_total' ), 99, 2 );
add_action( 'woocommerce_email_after_order_table', array( $this, 'show_store_credit_balance' ), 10, 3 );
add_filter( 'woocommerce_get_coupon_id_from_code', array( $this, 'get_coupon_id_from_code' ), 1000, 3 );
add_filter( 'woocommerce_order_item_get_discount', array( $this, 'smart_coupon_get_discount' ), 99, 2 );
}
/**
* Get single instance of WC_SC_Order_Fields
*
* @return WC_SC_Order_Fields Singleton object of WC_SC_Order_Fields
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Function to get total credit used in an order
*
* @param WC_Order $order The order object.
* @return float $total_credit_used
*/
public function get_total_credit_used_in_order( $order = null ) {
if ( empty( $order ) ) {
return 0;
}
$total_credit_used = 0;
if ( ! $this->is_old_sc_order( $order ) ) {
$smart_coupons_contribution = ( $this->is_callable( $order, 'get_meta' ) ) ? $order->get_meta( 'smart_coupons_contribution' ) : array();
if ( ! empty( $smart_coupons_contribution ) ) {
$total_credit_used = array_sum( $smart_coupons_contribution );
}
return $total_credit_used;
}
$coupons = $order->get_items( 'coupon' );
if ( ! empty( $coupons ) ) {
foreach ( $coupons as $item_id => $item ) {
$code = ( is_object( $item ) && is_callable( array( $item, 'get_code' ) ) ) ? $item->get_code() : $item['code'];
if ( empty( $code ) ) {
continue;
}
$coupon = new WC_Coupon( $code );
if ( ! empty( $coupon ) && $coupon instanceof WC_Coupon ) {
if ( $this->is_wc_gte_30() ) {
$coupon_discount_type = ( is_object( $coupon ) && is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
$discount_type = ( ! empty( $coupon_discount_type ) ) ? $coupon_discount_type : '';
} else {
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
}
if ( 'smart_coupon' !== $discount_type ) {
continue;
}
$discount = ( is_object( $item ) && is_callable( array( $item, 'get_discount' ) ) ) ? $item->get_discount() : $item['discount_amount'];
$discount_tax = ( is_object( $item ) && is_callable( array( $item, 'get_discount_tax' ) ) ) ? $item->get_discount_tax() : $item['discount_amount_tax'];
$total_credit_used += $discount;
$sc_include_tax = $this->is_store_credit_include_tax();
// Check if discount include tax.
if ( 'yes' === $sc_include_tax && ! empty( $discount_tax ) ) {
$total_credit_used += $discount_tax;
} else {
$prices_include_tax = ( 'incl' === get_option( 'woocommerce_tax_display_cart' ) ) ? true : false;
if ( true === $prices_include_tax ) {
$apply_before_tax = get_option( 'woocommerce_smart_coupon_apply_before_tax', 'no' );
if ( 'yes' === $apply_before_tax ) {
$_sc_include_tax = get_option( 'woocommerce_smart_coupon_include_tax', 'no' );
if ( 'no' === $_sc_include_tax ) {
$total_credit_used += $discount_tax;
}
}
}
}
}
}
}
return $total_credit_used;
}
/**
* Function to show store credit used in order admin panel
*
* @param int $order_id The order id.
*/
public function admin_order_totals_add_smart_coupons_discount_details( $order_id = 0 ) {
global $store_credit_label;
if ( empty( $order_id ) ) {
return;
}
if ( ! $this->is_old_sc_order( $order_id ) ) {
return;
}
$order = wc_get_order( $order_id );
$total_credit_used = $this->get_total_credit_used_in_order( $order );
if ( empty( $total_credit_used ) ) {
return;
}
?>
<tr>
<td class="label">
<?php
/* translators: %s: singular name for store credit */
echo ! empty( $store_credit_label['singular'] ) ? sprintf( esc_html__( '%s Used', 'woocommerce-smart-coupons' ), esc_html( ucwords( $store_credit_label['singular'] ) ) ) : esc_html__( 'Store Credit Used', 'woocommerce-smart-coupons' );
?>
<span class="tips" data-tip="<?php echo esc_attr__( 'This is the total credit used.', 'woocommerce-smart-coupons' ); ?>">[?]</span>:</td>
<td width="1%"></td>
<td class="total">
<?php
if ( $this->is_wc_gte_30() ) {
echo wc_price( $total_credit_used, array( 'currency' => $order->get_currency() ) ); // phpcs:ignore
} else {
echo wc_price( $total_credit_used, array( 'currency' => $order->get_order_currency() ) ); // phpcs:ignore
}
?>
</td>
</tr>
<?php
}
/**
* Function to add hooks based on conditions
*/
public function order_fields_hooks() {
if ( $this->is_wc_gte_30() ) {
add_filter( 'woocommerce_order_get_total_discount', array( $this, 'smart_coupons_order_amount_total_discount' ), 10, 2 );
} else {
add_filter( 'woocommerce_order_amount_total_discount', array( $this, 'smart_coupons_order_amount_total_discount' ), 10, 2 );
}
}
/**
* Function to add details of discount coming from Smart Coupons
*
* @param array $total_rows All rows.
* @param WC_Order $order The order object.
* @param string $tax_display Tax to display.
* @return array $total_rows
*/
public function add_smart_coupons_discount_details( $total_rows = array(), $order = null, $tax_display = '' ) {
global $store_credit_label;
if ( empty( $order ) ) {
return $total_rows;
}
$total_credit_used = (float) $this->get_total_credit_used_in_order( $order );
$offset = array_search( 'order_total', array_keys( $total_rows ), true );
if ( false !== $offset && ! empty( $total_credit_used ) && ! empty( $total_rows ) ) {
$total_rows = array_merge(
array_slice( $total_rows, 0, $offset ),
array(
'smart_coupon' => array(
/* translators: %s: singular name for store credit */
'label' => ! empty( $store_credit_label['singular'] ) ? sprintf( __( '%s Used:', 'woocommerce-smart-coupons' ), ucwords( $store_credit_label['singular'] ) ) : __( 'Store Credit Used:', 'woocommerce-smart-coupons' ),
'value' => '-' . wc_price( $total_credit_used ),
),
),
array_slice( $total_rows, $offset, null )
);
$total_discount = (float) $order->get_total_discount();
// code to check and manipulate 'Discount' amount based on Store Credit used.
if ( $total_discount === $total_credit_used ) {
unset( $total_rows['discount'] );
} else {
if ( $this->is_old_sc_order( $order ) ) {
$total_discount = $total_discount - $total_credit_used;
$total_rows['discount']['value'] = '-' . wc_price( $total_discount );
} else {
if ( 'incl' === $tax_display ) {
$total_discount_tax = $order->get_discount_tax();
$total_discount += $total_discount_tax;
}
if ( $total_discount > $total_credit_used ) {
$total_discount = $total_discount - $total_credit_used;
if ( ! array_key_exists( 'discount', $total_rows ) ) {
$total_rows['discount'] = array();
}
if ( ! array_key_exists( 'label', $total_rows['discount'] ) ) {
$total_rows['discount']['label'] = __( 'Discount:', 'woocommerce-smart-coupons' );
}
$total_rows['discount']['value'] = '-' . wc_price( $total_discount );
}
}
}
}
return $total_rows;
}
/**
* Function to include discounts from Smart Coupons in total discount of order
*
* @param float $total_discount Total discount.
* @param WC_Order $order The order object.
* @return float $total_discount
*/
public function smart_coupons_order_amount_total_discount( $total_discount, $order = null ) {
if ( ! $this->is_old_sc_order( $order ) ) {
return $total_discount;
}
// To avoid adding store credit in 'Discount' field on order admin panel.
if ( did_action( 'woocommerce_admin_order_item_headers' ) >= 1 ) {
return $total_discount;
}
$total_credit_used = $this->get_total_credit_used_in_order( $order );
if ( $total_credit_used > 0 ) {
$total_discount += $total_credit_used;
}
return $total_discount;
}
/**
* Function to add label for smart_coupons in cart total
*
* @param string $default_label Default label.
* @param WC_Coupon $coupon The coupon object.
* @return string $new_label
*/
public function cart_totals_smart_coupons_label( $default_label = '', $coupon = null ) {
global $store_credit_label;
if ( empty( $coupon ) ) {
return $default_label;
}
if ( $this->is_wc_gte_30() ) {
$discount_type = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_discount_type' ) ) ) ? $coupon->get_discount_type() : '';
$coupon_code = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
} else {
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
if ( ! empty( $discount_type ) && 'smart_coupon' === $discount_type ) {
$credit_label = ! empty( $store_credit_label['singular'] ) ? ucwords( $store_credit_label['singular'] ) . ':' : __( 'Store Credit:', 'woocommerce-smart-coupons' );
return $credit_label . ' ' . $coupon_code;
}
return $default_label;
}
/**
* Modify Tax detail HTML if store credit is applied, in cart
*
* @param string $html The total html.
* @return string $html
*/
public function cart_totals_order_total_html( $html = null ) {
if ( empty( $html ) ) {
return $html;
}
if ( ! class_exists( 'WCS_SC_Compatibility' ) ) {
include_once 'class-wcs-compatibility.php';
}
$is_display_price_incl_tax = ( $this->is_wc_gte_33() ) ? WC()->cart->display_prices_including_tax() : ( 'incl' === WC()->cart->tax_display_cart );
if ( wc_tax_enabled() && true === $is_display_price_incl_tax ) {
$applied_coupons = ( is_object( WC()->cart ) && is_callable( array( WC()->cart, 'get_applied_coupons' ) ) ) ? WC()->cart->get_applied_coupons() : array();
if ( empty( $applied_coupons ) ) {
return $html;
}
foreach ( $applied_coupons as $code ) {
$coupon = new WC_Coupon( $code );
if ( $this->is_wc_gte_30() ) {
$discount_type = $coupon->get_discount_type();
} else {
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
}
if ( ! is_a( $coupon, 'WC_Coupon' ) || 'smart_coupon' !== $discount_type ) {
continue;
}
if ( WC()->cart->get_total() === 0 || WC()->cart->get_total() <= WC()->cart->get_taxes_total() ) {
$cart_contains_subscription = WCS_SC_Compatibility::is_cart_contains_subscription();
$calculation_type = '';
if ( $cart_contains_subscription ) {
$calculation_type = WC_Subscriptions_Cart::get_calculation_type();
if ( 'recurring_total' !== $calculation_type ) {
return '<strong>' . WC()->cart->get_total() . '</strong> ';
} else {
return $html;
}
} else {
return '<strong>' . WC()->cart->get_total() . '</strong> ';
}
}
}
}
return $html;
}
/**
* Modify Tax detail HTML if store credit is applied, in order
*
* @param string $html The order total html.
* @param WC_Order $order The order object (optional).
* @return string $html
*/
public function get_formatted_order_total( $html = null, $order = null ) {
if ( empty( $html ) || empty( $order ) ) {
return $html;
}
if ( $this->is_wc_gte_30() ) {
$tax_display = get_option( 'woocommerce_tax_display_cart' );
} else {
$tax_display = ( ! empty( $order->tax_display_cart ) ) ? $order->tax_display_cart : '';
}
if ( wc_tax_enabled() && 'incl' === $tax_display ) {
$applied_coupons = $this->get_coupon_codes( $order );
if ( empty( $applied_coupons ) ) {
return $html;
}
foreach ( $applied_coupons as $code ) {
$coupon = new WC_Coupon( $code );
if ( $this->is_wc_gte_30() ) {
$discount_type = $coupon->get_discount_type();
} else {
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
}
if ( ! is_a( $coupon, 'WC_Coupon' ) || 'smart_coupon' !== $discount_type ) {
continue;
}
if ( $order->get_total() === 0 || $order->get_total() <= $order->get_total_tax() ) {
return wc_price( $order->get_total() );
}
}
}
return $html;
}
/**
* Function to notify user about remaining balance in Store Credit in "Order Complete" email
*
* @param WC_Order $order The order object.
* @param boolean $send_to_admin Is send to admin.
* @param boolean $plain_text Is plain text email.
*/
public function show_store_credit_balance( $order = false, $send_to_admin = false, $plain_text = false ) {
global $store_credit_label;
if ( $send_to_admin ) {
return;
}
if ( $this->is_wc_gte_30() ) {
$order_refunds = ( ! empty( $order ) && is_callable( array( $order, 'get_refunds' ) ) ) ? $order->get_refunds() : array();
} else {
$order_refunds = ( ! empty( $order->refunds ) ) ? $order->refunds : array();
}
if ( ! empty( $order_refunds ) ) {
return;
}
$used_coupons = $this->get_coupon_codes( $order );
if ( count( $used_coupons ) > 0 ) {
$store_credit_balance = '';
foreach ( $used_coupons as $code ) {
if ( ! $code ) {
continue;
}
$coupon = new WC_Coupon( $code );
if ( $this->is_wc_gte_30() ) {
$discount_type = $coupon->get_discount_type();
$coupon_code = $coupon->get_code();
} else {
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
$coupon_amount = $this->get_amount( $coupon, true, $order );
if ( 'smart_coupon' === $discount_type && $coupon_amount > 0 ) {
$store_credit_balance .= '<li><strong>' . $coupon_code . '</strong> &mdash; ' . wc_price( $coupon_amount ) . '</li>';
}
}
if ( ! empty( $store_credit_balance ) ) {
/* translators: %s: singular name for store credit */
$balance_left_txt = ! empty( $store_credit_label['singular'] ) ? sprintf( __( '%s Balance ', 'woocommerce-smart-coupons' ), esc_html( ucwords( $store_credit_label['singular'] ) ) ) : __( 'Store Credit / Gift Card Balance', 'woocommerce-smart-coupons' );
echo '<br /><h3>' . esc_html( $balance_left_txt ) . ': </h3>';
echo '<ul>' . wp_kses_post( $store_credit_balance ) . '</ul><br />'; // phpcs:ignore
}
}
}
/**
* Force try to find the coupon's id by code
* in some cases like when coupon is trashed
*
* @param integer $id The coupon's id.
* @param string $code The coupon code.
* @param integer $exclude_id Exclude coupon's id.
* @return integer
*/
public function get_coupon_id_from_code( $id = 0, $code = '', $exclude_id = 0 ) {
if ( empty( $id ) ) {
$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore
$backtrace_functions = wp_list_pluck( $backtrace, 'function' );
if ( in_array( 'get_total_credit_used_in_order', $backtrace_functions, true ) ) {
$index = array_search( 'get_total_credit_used_in_order', $backtrace_functions, true );
$traced = ( ! empty( $backtrace[ $index ] ) && 'WC_SC_Order_Fields' === $backtrace[ $index ]['class'] && 'get_total_credit_used_in_order' === $backtrace[ $index ]['function'] );
if ( true === $traced ) {
global $wpdb;
$post_id = $wpdb->get_var( // phpcs:ignore
$wpdb->prepare(
"
SELECT ID
FROM $wpdb->posts
WHERE post_title = %s
AND post_type = 'shop_coupon'
ORDER BY ID DESC
",
$code
)
);
if ( ! empty( $post_id ) ) {
return absint( $post_id );
}
}
}
}
return $id;
}
/**
* Function to get total discount applied by store credit.
*
* @param float $discount The original discount.
* @param WC_Order_Item_Coupon $order_item The coupon order item.
* @return float
*/
public function smart_coupon_get_discount( $discount = 0, $order_item = null ) {
if ( ( function_exists( 'wc_tax_enabled' ) && false === wc_tax_enabled() ) || ( get_option( 'woocommerce_calc_taxes' ) === 'no' ) ) {
return $discount;
}
$discount_tax = $this->is_callable( $order_item, 'get_discount_tax' ) ? $order_item->get_discount_tax() : 0;
if ( empty( $discount_tax ) ) {
return $discount;
}
$order_id = ( $this->is_callable( $order_item, 'get_order_id' ) ) ? $order_item->get_order_id() : 0;
if ( $this->is_old_sc_order( $order_id ) ) {
return $discount;
}
if ( is_admin() && $order_item->is_type( 'coupon' ) ) {
if ( $this->is_wc_gte_87() ) {
$coupon_data = json_decode( $order_item->get_meta( 'coupon_info' ), true );
$discount_type = isset( $coupon_data[2] ) && ! empty( $coupon_data[2] ) ? $coupon_data[2] : '';
} else {
$coupon_data = $order_item->get_meta( 'coupon_data' );
$discount_type = isset( $coupon_data['discount_type'] ) && ! empty( $coupon_data['discount_type'] ) ? $coupon_data['discount_type'] : '';
}
if ( ! empty( $discount_type ) && 'smart_coupon' === $discount_type ) {
$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore
if ( ! empty( $backtrace ) && is_array( $backtrace ) ) {
$args = array();
foreach ( $backtrace as $trace ) {
if ( array_key_exists( 'args', $trace ) ) {
$args = array_merge( $args, array_values( $trace['args'] ) );
}
}
$args = array_filter( array_unique( $args ) );
if ( ! empty( $args ) && is_array( $args ) ) {
foreach ( $args as $path ) {
if ( stripos( $path, 'admin/meta-boxes/views/html-order-items.php' ) !== false ) {
$discount += $discount_tax;
break;
}
}
}
}
}
}
return $discount;
}
}
}
WC_SC_Order_Fields::get_instance();

View File

@@ -0,0 +1,470 @@
<?php
/**
* Coupons via URL
*
* @author StoreApps
* @since 4.7.0
* @version 1.4.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Print_Coupon' ) ) {
/**
* Class for handling coupons applied via URL
*/
class WC_SC_Print_Coupon {
/**
* Variable to hold instance of WC_SC_Print_Coupon
*
* @var $instance
*/
private static $instance = null;
/**
* HTML template path.
*
* @var string
*/
private $template_html;
/**
* Template path.
*
* @var string
*/
private $template_base;
/**
* Constructor
*/
private function __construct() {
// Use our plugin templates directory as the template base.
$this->template_base = dirname( WC_SC_PLUGIN_FILE ) . '/templates/';
// Email template location.
$print_style = get_option( 'wc_sc_coupon_print_style', 'default' );
$this->template_html = 'print-coupons-' . $print_style . '.php';
add_action( 'init', array( $this, 'may_be_save_terms_page' ) );
add_action( 'admin_notices', array( $this, 'may_be_show_terms_notice' ) );
add_action( 'wp_ajax_wc_sc_terms_notice_action', array( $this, 'terms_notice_action' ) );
add_action( 'wp_loaded', array( $this, 'print_coupon_from_url' ), 20 );
add_filter( 'display_post_states', array( $this, 'display_post_states' ), 10, 2 );
add_filter( 'pre_delete_post', array( $this, 'prevent_deletion_of_terms_page' ), 10, 3 );
add_filter( 'pre_trash_post', array( $this, 'prevent_deletion_of_terms_page' ), 10, 2 );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts_and_styles' ), 99 );
}
/**
* Get single instance of WC_SC_Print_Coupon
*
* @return WC_SC_Print_Coupon Singleton object of WC_SC_Print_Coupon
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Function to create and save terms page if already not created
*/
public function may_be_save_terms_page() {
$terms_page_option = $this->get_terms_page_option();
$terms_page_id = get_option( $terms_page_option, false );
// If terms page option is not created yet or may be deleted.
if ( empty( $terms_page_id ) ) {
$terms_page_id = $this->add_terms_page();
$this->update_terms_page_option( $terms_page_id );
}
}
/**
* Function to add create terms page
*/
public function add_terms_page() {
$name = _x( 'wc-sc-coupons-terms', 'Page slug', 'woocommerce-smart-coupons' );
$title = _x( 'Smart Coupons Terms', 'Page title', 'woocommerce-smart-coupons' );
$terms_page_id = $this->create_page( $name, $title, '', 'private' );
return $terms_page_id;
}
/**
* Utility function for creating Smart Coupons' pages
*
* @param string $slug Page slug.
* @param string $page_title Page title.
* @param string $page_content Page content.
* @param string $post_status Page status.
* @param int $post_parent Page parent.
* @return int $page_id Create page id
*/
public function create_page( $slug = '', $page_title = '', $page_content = '', $post_status = 'publish', $post_parent = 0 ) {
$page_id = 0;
if ( empty( $slug ) ) {
return $page_id;
}
$args = array(
'role' => 'administrator',
'orderby' => 'ID',
'order' => 'ASC',
'fields' => 'ID',
);
$admin_user_ids = get_users( $args );
$page_data = array(
'post_author' => current( $admin_user_ids ),
'post_status' => $post_status,
'post_type' => 'page',
'post_name' => $slug,
'post_title' => $page_title,
'post_content' => $page_content,
'post_parent' => $post_parent,
'comment_status' => 'closed',
);
$page_id = wp_insert_post( $page_data );
return $page_id;
}
/**
* Function to get terms page id
*/
public function get_terms_page_id() {
$terms_page_option = $this->get_terms_page_option();
$terms_page_id = get_option( $terms_page_option, false );
return $terms_page_id;
}
/**
* Function to get the option key name for terms page
*/
public function get_terms_page_option() {
// Option key name for Smart Coupons' term page id.
$terms_page_option = 'wc_sc_terms_page_id';
return $terms_page_option;
}
/**
* Function to update terms' page id in the options table
*
* @param int $terms_page_id Page parent.
*/
public function update_terms_page_option( $terms_page_id = 0 ) {
if ( ! empty( $terms_page_id ) && is_numeric( $terms_page_id ) ) {
$terms_page_option = $this->get_terms_page_option();
update_option( $terms_page_option, $terms_page_id, 'no' );
}
}
/**
* Function to show notice for entering terms' page content
*/
public function may_be_show_terms_notice() {
global $pagenow, $post;
$is_coupon_enabled = wc_coupons_enabled();
// Don't show message if coupons are not enabled.
if ( false === $is_coupon_enabled ) {
return;
}
$terms_page_id = $this->get_terms_page_id();
// Return if terms page hasn't been set.
if ( empty( $terms_page_id ) ) {
return;
}
$valid_post_types = array( 'shop_coupon', 'shop_order', 'product' );
$valid_pagenow = array( 'edit.php', 'post.php', 'plugins.php' );
$is_show_terms_notice = get_option( 'wc_sc_is_show_terms_notice', false );
$get_post_type = ( ! empty( $post->ID ) ) ? $this->get_post_type( $post->ID ) : '';
$get_page = ( ! empty( $_GET['page'] ) ) ? wc_clean( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
$get_tab = ( ! empty( $_GET['tab'] ) ) ? wc_clean( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore
$is_page = ( in_array( $pagenow, $valid_pagenow, true ) || in_array( $get_post_type, $valid_post_types, true ) || ( 'admin.php' === $pagenow && ( 'wc-smart-coupons' === $get_page || 'wc-smart-coupons' === $get_tab ) ) );
// Terms page notice.
if ( $is_page && 'no' !== $is_show_terms_notice ) {
if ( ! wp_script_is( 'jquery' ) ) {
wp_enqueue_script( 'jquery' );
}
?>
<style type="text/css" media="screen">
#wc_sc_terms_notice .wc_sc_terms_notice_action {
float: right;
padding: 0.5em 0;
text-align: right;
}
</style>
<script type="text/javascript">
jQuery(function(){
jQuery('body').on('click', '#wc_sc_terms_notice a.wc_sc_terms_notice_remove, #wc_sc_terms_notice a.wc_sc_terms_redirect', function(){
let notice_action = jQuery( this ).data('action');
jQuery.ajax({
url: decodeURIComponent( '<?php echo rawurlencode( admin_url( 'admin-ajax.php' ) ); ?>' ),
type: 'post',
dataType: 'json',
data: {
action: 'wc_sc_terms_notice_action',
security: '<?php echo esc_html( wp_create_nonce( 'wc-sc-terms-notice-action' ) ); ?>',
do: notice_action
},
success: function( response ){
if ( response.success != undefined && response.success != '' && response.success == 'yes' ) {
if( response.redirect_url != undefined && response.redirect_url != '' ) {
window.location.href = response.redirect_url;
} else {
jQuery('#wc_sc_terms_notice').fadeOut(500, function(){ jQuery('#wc_sc_terms_notice').remove(); });
}
}
}
});
return false;
});
});
</script>
<div id="wc_sc_terms_notice" class="updated fade">
<div class="wc_sc_terms_notice_action">
<a href="javascript:void(0)" class="wc_sc_terms_notice_remove" data-action="remove"><?php echo esc_html__( 'Never show again', 'woocommerce-smart-coupons' ); ?></a>
</div>
<p>
<?php echo esc_html__( 'Smart Coupons has created a coupon\'s terms page (used during coupon printing) for you. Please edit it as required from', 'woocommerce-smart-coupons' ) . ' <a href="javascript:void(0)" class="wc_sc_terms_redirect" data-action="redirect">' . esc_html__( 'here', 'woocommerce-smart-coupons' ) . '</a>'; ?>
</p>
</div>
<?php
}
}
/**
* Function to handle Smart Coupons terms notice action
*/
public function terms_notice_action() {
check_ajax_referer( 'wc-sc-terms-notice-action', 'security' );
$post_do = ( ! empty( $_POST['do'] ) ) ? wc_clean( wp_unslash( $_POST['do'] ) ) : ''; // phpcs:ignore
if ( empty( $post_do ) ) {
return;
}
$response = array(
'success' => 'no',
);
$option_updated = update_option( 'wc_sc_is_show_terms_notice', 'no', 'no' );
if ( true === $option_updated ) {
$response['success'] = 'yes';
if ( 'redirect' === $post_do ) {
$terms_page_id = $this->get_terms_page_id();
$terms_edit_url = get_edit_post_link( $terms_page_id, 'edit' );
if ( ! empty( $terms_edit_url ) ) {
$response['redirect_url'] = $terms_edit_url;
}
}
}
wp_send_json( $response );
}
/**
* Print coupon codes along with terms' page content
*/
public function print_coupon_from_url() {
global $woocommerce_smart_coupon;
if ( empty( $_SERVER['QUERY_STRING'] ) ) {
return;
}
parse_str( wp_unslash( $_SERVER['QUERY_STRING'] ), $coupon_args ); // phpcs:ignore
$coupon_args = wc_clean( $coupon_args );
if ( ! empty( $coupon_args['print-coupons'] ) && 'yes' === $coupon_args['print-coupons'] && ! empty( $coupon_args['source'] ) && 'wc-smart-coupons' === $coupon_args['source'] && ! empty( $coupon_args['coupon-codes'] ) ) {
$coupon_args['coupon-codes'] = urldecode( $coupon_args['coupon-codes'] );
$coupon_codes = explode( ',', $coupon_args['coupon-codes'] );
$coupon_codes = array_filter( $coupon_codes ); // Remove empty coupon codes if any.
$coupons_data = array();
foreach ( $coupon_codes as $coupon_code ) {
if ( empty( $coupon_code ) ) {
continue;
}
$coupons_data[] = array(
'code' => $coupon_code,
);
}
if ( ! empty( $coupons_data ) ) {
$terms_page_id = $this->get_terms_page_id();
$terms_page_title = '';
$terms_page_content = '';
if ( ! empty( $terms_page_id ) ) {
$terms_page = get_post( $terms_page_id );
if ( is_a( $terms_page, 'WP_Post' ) ) {
$terms_page_title = ( ! empty( $terms_page->post_title ) ) ? $terms_page->post_title : '';
$terms_page_content = ( ! empty( $terms_page->post_content ) ) ? $terms_page->post_content : '';
if ( ! empty( $terms_page_content ) ) {
$terms_page_content = apply_filters( 'the_content', $terms_page_content );
}
}
}
$design = get_option( 'wc_sc_setting_coupon_design', 'basic' );
$background_color = get_option( 'wc_sc_setting_coupon_background_color', '#39cccc' );
$foreground_color = get_option( 'wc_sc_setting_coupon_foreground_color', '#30050b' );
$third_color = get_option( 'wc_sc_setting_coupon_third_color', '#39cccc' );
$show_coupon_description = get_option( 'smart_coupons_show_coupon_description', 'no' );
$valid_designs = $this->get_valid_coupon_designs();
if ( ! in_array( $design, $valid_designs, true ) ) {
$design = 'basic';
}
$coupon_styles = $woocommerce_smart_coupon->get_coupon_styles( $design );
$default_path = $this->template_base;
$template_path = $woocommerce_smart_coupon->get_template_base_dir( $this->template_html );
wc_get_template(
$this->template_html,
array(
'coupon_codes' => $coupons_data,
'terms_page_title' => $terms_page_title,
'terms_page_content' => $terms_page_content,
'background_color' => $background_color,
'foreground_color' => $foreground_color,
'third_color' => $third_color,
'coupon_styles' => $coupon_styles,
'design' => $design,
'show_coupon_description' => $show_coupon_description,
),
$template_path,
$default_path
);
}
exit;
}
}
/**
* Add display state for printable coupon's terms page
*
* @param array $post_states An array of post display states.
* @param WP_Post $post The current post object.
*/
public function display_post_states( $post_states, $post ) {
$terms_page_id = $this->get_terms_page_id();
if ( ! empty( $post->ID ) && ! empty( $terms_page_id ) && absint( $terms_page_id ) === absint( $post->ID ) ) {
if ( isset( $post_states['private'] ) ) {
unset( $post_states['private'] );
}
$post_states['wc_sc_coupons_terms'] = __( 'Used during coupon printing', 'woocommerce-smart-coupons' );
}
return $post_states;
}
/**
* Prevent Deletion Of Terms Page
*
* @param mixed $is_delete Whether to allow deletion or not.
* @param WP_Post $post The post to delete.
* @param boolean $force_delete Whether to permanently delete or not.
* @return mixed
*/
public function prevent_deletion_of_terms_page( $is_delete = null, $post = null, $force_delete = false ) {
$terms_page_id = $this->get_terms_page_id();
if ( ! empty( $post->ID ) && ! empty( $terms_page_id ) && absint( $terms_page_id ) === absint( $post->ID ) ) {
return false;
}
return $is_delete;
}
/**
* Scripts & styles
*/
public function enqueue_scripts_and_styles() {
global $woocommerce_smart_coupon;
if ( empty( $_SERVER['QUERY_STRING'] ) ) {
return;
}
parse_str( wp_unslash( $_SERVER['QUERY_STRING'] ), $coupon_args ); // phpcs:ignore
$coupon_args = wc_clean( $coupon_args );
$design = get_option( 'wc_sc_setting_coupon_design', 'basic' );
if ( ! empty( $coupon_args['print-coupons'] ) && 'yes' === $coupon_args['print-coupons'] && ! empty( $coupon_args['source'] ) && 'wc-smart-coupons' === $coupon_args['source'] && ! empty( $coupon_args['coupon-codes'] ) ) {
if ( 'custom-design' !== $design ) {
if ( ! wp_style_is( 'smart-coupon-designs' ) ) {
wp_enqueue_style( 'smart-coupon-designs' );
}
}
}
}
}
}
WC_SC_Print_Coupon::get_instance();

View File

@@ -0,0 +1,835 @@
<?php
/**
* Handle privacy of customers
*
* @author StoreApps
* @since 3.3.0
* @version 1.5.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_Abstract_Privacy' ) ) {
return;
}
if ( ! class_exists( 'WC_SC_Privacy' ) ) {
/**
* Class for handling privacy for customer & maintaining GDPR compliance of the plugin
*/
class WC_SC_Privacy extends WC_Abstract_Privacy {
/**
* Variable to hold instance of WC_SC_Privacy
*
* @var $instance
*/
private static $instance = null;
/**
* Plugin data
*
* @var $plugin_data
*/
public $plugin_data = array();
/**
* Constructor
*/
public function __construct() {
$this->plugin_data = WC_Smart_Coupons::get_smart_coupons_plugin_data();
parent::__construct( $this->plugin_data['Name'] );
/* translators: Plugin's name */
$this->add_exporter( WC_SC_PLUGIN_DIRNAME . '-coupon-data-exporter', sprintf( __( '%s - Coupon Personal Data Exporter', 'woocommerce-smart-coupons' ), $this->plugin_data['Name'] ), array( $this, 'wc_sc_coupon_data_exporter' ) );
/* translators: Plugin's name */
$this->add_eraser( WC_SC_PLUGIN_DIRNAME . '-coupon-data-eraser', sprintf( __( '%s - Coupon Personal Data Eraser', 'woocommerce-smart-coupons' ), $this->plugin_data['Name'] ), array( $this, 'wc_sc_coupon_data_eraser' ) );
/* translators: Plugin's name */
$this->add_exporter( WC_SC_PLUGIN_DIRNAME . '-order-data-exporter', sprintf( __( '%s - Order Personal Data Exporter', 'woocommerce-smart-coupons' ), $this->plugin_data['Name'] ), array( $this, 'wc_sc_order_data_exporter' ) );
/* translators: Plugin's name */
$this->add_eraser( WC_SC_PLUGIN_DIRNAME . '-order-data-eraser', sprintf( __( '%s - Order Personal Data Eraser', 'woocommerce-smart-coupons' ), $this->plugin_data['Name'] ), array( $this, 'wc_sc_order_data_eraser' ) );
/* translators: Plugin's name */
$this->add_exporter( WC_SC_PLUGIN_DIRNAME . '-user-data-exporter', sprintf( __( '%s - User Personal Data Exporter', 'woocommerce-smart-coupons' ), $this->plugin_data['Name'] ), array( $this, 'wc_sc_user_data_exporter' ) );
/* translators: Plugin's name */
$this->add_eraser( WC_SC_PLUGIN_DIRNAME . '-user-data-eraser', sprintf( __( '%s - User Personal Data Eraser', 'woocommerce-smart-coupons' ), $this->plugin_data['Name'] ), array( $this, 'wc_sc_user_data_eraser' ) );
add_action( 'woocommerce_privacy_before_remove_order_personal_data', array( $this, 'remove_order_personal_data' ) );
add_filter( 'woocommerce_get_settings_account', array( $this, 'account_settings' ) );
}
/**
* Get single instance of WC_SC_Privacy
*
* @return WC_SC_Privacy Singleton object of WC_SC_Privacy
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Gets the message of the privacy to display.
*/
public function get_privacy_message() {
$content = '<h2>' . esc_html__( 'Store Credit/Gift Certificate', 'woocommerce-smart-coupons' ) . '</h2>
<strong>' . esc_html__( 'What we access?', 'woocommerce-smart-coupons' ) . '</strong>
<ul>
<li>' . esc_html__( 'If you are logged in: We access your billing email address saved in your account & billing email address entered during purchase', 'woocommerce-smart-coupons' ) . '</li>
<li>' . esc_html__( 'If you are a visitor: We access your billing email address entered during purchase', 'woocommerce-smart-coupons' ) . '</li>
</ul>
<strong>' . esc_html__( 'What we store & why?', 'woocommerce-smart-coupons' ) . '</strong>
<ul>
<li>' . esc_html__( 'Coupon code generated for you', 'woocommerce-smart-coupons' ) . '</li>
<li>' . esc_html__( 'Coupon code passed via URL', 'woocommerce-smart-coupons' ) . '</li>
<li>' . esc_html__( 'Coupon amount, email & message entered for gift card receiver', 'woocommerce-smart-coupons' ) . '</li>
</ul>
<p>' . esc_html__( 'We store these data so that we can process it for you whenever required.', 'woocommerce-smart-coupons' ) . '</p>';
return $content;
}
/**
* Returns Smart Coupons data based on email.
*
* @param string $email_address The email address.
* @param int $page Pagination.
*
* @return array
*/
protected function get_wc_sc_data( $email_address, $page ) {
global $wpdb;
$wpdb->query( $wpdb->prepare( 'SET SESSION group_concat_max_len=%d', 999999 ) ); // phpcs:ignore
$results = wp_cache_get( 'wc_sc_coupon_data_' . sanitize_key( $email_address ), 'woocommerce_smart_coupons' );
if ( false === $results ) {
$results = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
"SELECT p.ID,
p.post_title,
p.post_date,
GROUP_CONCAT( pm.meta_key ORDER BY pm.meta_id SEPARATOR '###' ) AS meta_keys,
GROUP_CONCAT( pm.meta_value ORDER BY pm.meta_id SEPARATOR '###' ) AS meta_values
FROM $wpdb->posts AS p
LEFT JOIN $wpdb->postmeta AS pm
ON ( p.ID = pm.post_id AND p.post_type = %s AND pm.meta_key IN ( %s, %s, %s ) )
WHERE pm.meta_value = %s
OR pm.meta_value LIKE %s
OR pm.meta_value <> ''
GROUP BY p.ID
ORDER BY p.ID",
'shop_coupon',
'discount_type',
'customer_email',
'generated_from_order_id',
'smart_coupon',
'%' . $wpdb->esc_like( '"' . $email_address . '"' ) . '%'
),
ARRAY_A
);
wp_cache_set( 'wc_sc_coupon_data_' . sanitize_key( $email_address ), $results, 'woocommerce_smart_coupons' );
$this->maybe_add_cache_key( 'wc_sc_coupon_data_' . sanitize_key( $email_address ) );
}
$coupon_data = array();
if ( ! empty( $results ) ) {
foreach ( $results as $result ) {
$meta_keys = ( ! empty( $result['meta_keys'] ) ) ? explode( '###', $result['meta_keys'] ) : array();
$meta_values = ( ! empty( $result['meta_values'] ) ) ? explode( '###', $result['meta_values'] ) : array();
if ( count( $meta_keys ) === count( $meta_values ) ) {
$meta_values = array_map( 'maybe_unserialize', $meta_values );
$meta = array_combine( $meta_keys, $meta_values );
if ( empty( $meta['discount_type'] ) || 'smart_coupon' !== $meta['discount_type'] ) {
continue;
}
unset( $meta['discount_type'] );
if ( empty( $meta['customer_email'] ) ) {
continue;
}
$customer_emails = array_unique( $meta['customer_email'] );
$common_email = array_intersect( array( $email_address ), $customer_emails );
if ( empty( $common_email ) ) {
continue;
}
$meta['customer_email'] = current( $common_email );
} else {
continue;
}
if ( empty( $coupon_data[ $result['ID'] ] ) || ! is_array( $coupon_data[ $result['ID'] ] ) ) {
$coupon_data[ $result['ID'] ] = array();
}
$coupon_data[ $result['ID'] ]['coupon_id'] = $result['ID'];
$coupon_data[ $result['ID'] ]['coupon_code'] = $result['post_title'];
$coupon_data[ $result['ID'] ]['created_date'] = $result['post_date'];
if ( ! empty( $meta ) ) {
foreach ( $meta as $key => $value ) {
$coupon_data[ $result['ID'] ][ $key ] = $value;
}
}
}
}
return $coupon_data;
}
/**
* Handle exporting data for Smart Coupons' Coupon data.
*
* @param string $email_address E-mail address to export.
* @param int $page Pagination of data.
*
* @return array
*/
public function wc_sc_coupon_data_exporter( $email_address, $page = 0 ) {
$done = false;
$data_to_export = array();
$coupon_data = $this->get_wc_sc_data( $email_address, (int) $page );
if ( 0 < count( $coupon_data ) ) {
$data = array();
$index = 0;
foreach ( $coupon_data as $coupon_id => $coupon ) {
$data[] = array(
'name' => $coupon['coupon_code'],
'value' => $coupon['customer_email'],
);
}
$data_to_export[] = array(
'group_id' => 'wc_smart_coupons_coupon_data',
'group_label' => __( 'Store Credit/Gift Certificate - Coupon Data', 'woocommerce-smart-coupons' ),
'item_id' => 'wc-smart-coupons-coupon-data-' . sanitize_title( $email_address ),
'data' => $data,
);
$done = 10 > count( $coupon_data );
} else {
$done = true;
}
return array(
'data' => $data_to_export,
'done' => $done,
);
}
/**
* Finds and erases Smart Coupons by email address.
*
* @param string $email_address The user email address.
* @param int $page Pagination.
* @return array An array of personal data in name value pairs
*/
public function wc_sc_coupon_data_eraser( $email_address, $page ) {
$coupon_data = $this->get_wc_sc_data( $email_address, (int) $page );
$done = false;
$items_removed = false;
$items_retained = false;
$messages = array();
foreach ( $coupon_data as $coupon ) {
list( $removed, $retained, $msgs ) = $this->maybe_handle_coupon_data( $coupon );
$items_removed |= $removed;
$items_retained |= $retained;
$messages = array_merge( $messages, $msgs );
}
// Tell core if we have more coupons to work on still.
$done = count( $coupon_data ) < 10;
return array(
'items_removed' => $items_removed,
'items_retained' => $items_retained,
'messages' => $messages,
'done' => $done,
);
}
/**
* Handle eraser of Coupon data
*
* @param array $coupon The coupon data.
* @return array
*/
protected function maybe_handle_coupon_data( $coupon ) {
if ( empty( $coupon ) || ! $this->is_retention_expired( $coupon['created_date'] ) ) {
return array( false, false, array() );
}
if ( $this->is_wc_gte_30() ) {
$_coupon = ( ! empty( $coupon['coupon_id'] ) ) ? new WC_Coupon( $coupon['coupon_id'] ) : null;
if ( $this->is_callable( $_coupon, 'delete_meta_data' ) && $this->is_callable( $_coupon, 'save' ) && $this->is_callable( $_coupon, 'delete' ) ) {
if ( $this->is_callable( $_coupon, 'set_email_restrictions' ) ) {
$_coupon->set_email_restrictions( array() );
}
$_coupon->delete_meta_data( 'customer_email' );
$_coupon->delete_meta_data( 'generated_from_order_id' );
$_coupon->save();
$_coupon->delete( true );
}
} else {
delete_post_meta( $coupon['coupon_id'], 'customer_email' );
delete_post_meta( $coupon['coupon_id'], 'generated_from_order_id' );
wp_delete_post( $coupon['coupon_id'], true );
}
return array( true, false, array( '<strong>' . __( 'Store Credit/Gift Certificate', 'woocommerce-smart-coupons' ) . '</strong> - ' . __( 'Removed Coupon Personal Data', 'woocommerce-smart-coupons' ) ) );
}
/**
* Returns Smart Coupons data based on email.
*
* @param string $email_address The email addres.
* @param int $page Pagination.
*
* @return array
*/
protected function get_wc_sc_user_data( $email_address, $page ) {
$user_data = array();
$user = get_user_by( 'email', $email_address );
if ( ! empty( $user->ID ) ) {
$sc_shortcode_generated_coupons = get_user_meta( $user->ID, '_sc_shortcode_generated_coupons', true );
if ( ! empty( $sc_shortcode_generated_coupons ) ) {
$user_data['shortcode'] = array();
foreach ( $sc_shortcode_generated_coupons as $sc_shortcode_generated_coupons ) {
$user_data['shortcode'][] = implode( ', ', $sc_shortcode_generated_coupons );
}
}
$sc_applied_coupon_from_url = get_user_meta( $user->ID, 'sc_applied_coupon_from_url', true );
if ( ! empty( $sc_applied_coupon_from_url ) ) {
$user_data['url'] = implode( ', ', $sc_applied_coupon_from_url );
}
}
return $user_data;
}
/**
* Handle exporting data for Smart Coupons User data.
*
* @param string $email_address E-mail address to export.
* @param int $page Pagination of data.
*
* @return array
*/
public function wc_sc_user_data_exporter( $email_address, $page = 0 ) {
$done = false;
$data_to_export = array();
$user_data = $this->get_wc_sc_user_data( $email_address, (int) $page );
if ( 0 < count( $user_data ) ) {
$shortcode = array();
$url = array();
$index = 0;
foreach ( $user_data as $key => $value ) {
if ( 'shortcode' === $key ) {
foreach ( $value as $val ) {
$shortcode[] = array(
'name' => __( 'Coupon', 'woocommerce-smart-coupons' ),
'value' => $val,
);
}
$data_to_export[] = array(
'group_id' => 'wc_smart_coupons_coupon_shortcode_data',
'group_label' => __( 'Generated Coupon Data', 'woocommerce-smart-coupons' ),
'item_id' => 'wc-smart-coupons-shorcode-data-' . sanitize_title( $email_address ),
'data' => $shortcode,
);
} elseif ( 'url' === $key ) {
$url[] = array(
'name' => __( 'Coupon' ),
'value' => $value,
);
$data_to_export[] = array(
'group_id' => 'wc_smart_coupons_url_data',
'group_label' => __( 'Coupon passed in URL', 'woocommerce-smart-coupons' ),
'item_id' => 'wc-smart-coupons-url-data-' . sanitize_title( $email_address ),
'data' => $url,
);
}
}
$done = 10 > count( $user_data );
} else {
$done = true;
}
return array(
'data' => $data_to_export,
'done' => $done,
);
}
/**
* Finds and erases Smart Coupons by email address.
*
* @param string $email_address The user email address.
* @param int $page Pagination.
* @return array An array of personal data in name value pairs
*/
public function wc_sc_user_data_eraser( $email_address, $page ) {
$user = get_user_by( 'email', $email_address );
$done = false;
$items_removed = false;
$items_retained = false;
$messages = array();
if ( ! empty( $user->ID ) ) {
$meta_keys = array( '_sc_shortcode_generated_coupons', 'sc_applied_coupon_from_url' );
foreach ( $meta_keys as $meta_key ) {
delete_user_meta( $user->ID, $meta_key );
$removed = true;
$retained = false;
$msgs = array( '<strong>' . __( 'Store Credit/Gift Certificate', 'woocommerce-smart-coupons' ) . '</strong> - ' . __( 'Removed User Personal Data', 'woocommerce-smart-coupons' ) );
$items_removed |= $removed;
$items_retained |= $retained;
$messages = array_merge( $messages, $msgs );
}
}
// Tell core if we have more coupons to work on still.
$done = true;
return array(
'items_removed' => $items_removed,
'items_retained' => $items_retained,
'messages' => $messages,
'done' => $done,
);
}
/**
* Returns Smart Coupons data based on email.
*
* @param string $email_address The email address.
* @param int $page Pagination.
*
* @return array
*/
protected function get_wc_sc_order_data( $email_address, $page ) {
global $wpdb;
$user = get_user_by( 'email', $email_address );
$order_ids = wp_cache_get( 'wc_sc_order_ids_for_' . sanitize_key( $email_address ), 'woocommerce_smart_coupons' );
if ( false === $order_ids ) {
if ( $this->is_hpos() ) {
$order_ids = $wpdb->get_col( // phpcs:ignore
$wpdb->prepare(
"SELECT id
FROM {$wpdb->prefix}wc_orders
WHERE customer_id = %d",
$user->ID
)
);
} else {
$order_ids = $wpdb->get_col( // phpcs:ignore
$wpdb->prepare(
"SELECT pm.post_id
FROM {$wpdb->posts} AS p
LEFT JOIN {$wpdb->postmeta} AS pm
ON ( p.ID = pm.post_id AND p.post_type = %s )
WHERE pm.meta_key = %s
AND pm.meta_value = %d",
'shop_order',
'_customer_user',
$user->ID
)
);
}
wp_cache_set( 'wc_sc_order_ids_for_' . sanitize_key( $email_address ), $order_ids, 'woocommerce_smart_coupons' );
$this->maybe_add_cache_key( 'wc_sc_order_ids_for_' . sanitize_key( $email_address ) );
}
if ( empty( $order_ids ) ) {
return array();
}
$how_many = count( $order_ids );
$placeholders = array_fill( 0, $how_many, '%d' );
if ( $this->is_hpos() ) {
$query = $wpdb->prepare(
"SELECT o.id,
om.meta_value AS sc_coupon_receiver_details
FROM {$wpdb->prefix}wc_orders AS o
LEFT JOIN {$wpdb->prefix}wc_orders_meta AS om
ON ( o.id = om.id AND om.meta_key = %s )",
'sc_coupon_receiver_details'
);
$query .= $wpdb->prepare( 'WHERE o.id IN (' . implode( ',', $placeholders ) . ') ', $order_ids ); // phpcs:ignore
$query .= $wpdb->prepare(
' AND om.meta_value <> %s
GROUP BY o.id
ORDER BY o.id',
''
);
} else {
$query = $wpdb->prepare(
"SELECT p.ID,
pm.meta_value AS sc_coupon_receiver_details
FROM $wpdb->posts AS p
LEFT JOIN $wpdb->postmeta AS pm
ON ( p.ID = pm.post_id AND p.post_type = %s AND pm.meta_key = %s )",
'shop_order',
'sc_coupon_receiver_details'
);
$query .= $wpdb->prepare( 'WHERE p.ID IN (' . implode( ',', $placeholders ) . ') ', $order_ids ); // phpcs:ignore
$query .= $wpdb->prepare(
' AND pm.meta_value <> %s
GROUP BY p.ID
ORDER BY p.ID',
''
);
}
$unique_order_ids = array_unique( $order_ids );
$results = wp_cache_get( 'wc_sc_receiver_detail_in_orders_' . implode( '_', $unique_order_ids ), 'woocommerce_smart_coupons' );
if ( false === $results ) {
$results = $wpdb->get_results( $query, ARRAY_A ); // phpcs:ignore
wp_cache_set( 'wc_sc_receiver_detail_in_orders_' . implode( '_', $unique_order_ids ), $results, 'woocommerce_smart_coupons' );
$this->maybe_add_cache_key( 'wc_sc_receiver_detail_in_orders_' . implode( '_', $unique_order_ids ) );
}
$order_data = array();
if ( ! empty( $results ) ) {
foreach ( $results as $result ) {
$order_data[ $result['ID'] ] = maybe_unserialize( $result['sc_coupon_receiver_details'] );
}
}
return $order_data;
}
/**
* Handle exporting data for Smart Coupons User data.
*
* @param string $email_address E-mail address to export.
* @param int $page Pagination of data.
*
* @return array
*/
public function wc_sc_order_data_exporter( $email_address, $page = 0 ) {
$done = false;
$data_to_export = array();
$order_data = $this->get_wc_sc_order_data( $email_address, (int) $page );
if ( 0 < count( $order_data ) ) {
$index = 0;
foreach ( $order_data as $key => $value ) {
foreach ( $value as $val ) {
$index++;
$data = array();
foreach ( $val as $k => $v ) {
if ( $val['email'] !== $email_address && 'code' === $k ) {
continue;
}
switch ( $k ) {
case 'code':
$name = __( 'Coupon Code', 'woocommerce-smart-coupons' );
break;
case 'amount':
$name = __( 'Coupon Amount', 'woocommerce-smart-coupons' );
break;
case 'email':
$name = __( 'Coupon For', 'woocommerce-smart-coupons' );
break;
case 'message':
$name = __( 'Message', 'woocommerce-smart-coupons' );
break;
}
$data[] = array(
'name' => $name,
'value' => $v,
);
}
$data_to_export[] = array(
'group_id' => 'wc_smart_coupons_order_data_' . $index,
'group_label' => __( 'Store Credit/Gift Certificate - Order Data', 'woocommerce-smart-coupons' ),
'item_id' => 'wc-smart-coupons-order-data-' . $index,
'data' => $data,
);
}
}
$done = 10 > count( $order_data );
} else {
$done = true;
}
return array(
'data' => $data_to_export,
'done' => $done,
);
}
/**
* Finds and erases Smart Coupons by email address.
*
* @param string $email_address The user email address.
* @param int $page Pagination.
* @return array An array of personal data in name value pairs
*/
public function wc_sc_order_data_eraser( $email_address, $page ) {
global $wpdb;
$user = get_user_by( 'email', $email_address );
$orders = wp_cache_get( 'wc_sc_order_by_email_for_' . $user->ID, 'woocommerce_smart_coupons' );
if ( false === $orders ) {
if ( $this->is_hpos() ) {
$orders = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
"SELECT date_created_gmt AS created_date,
id
FROM {$wpdb->prefix}wc_orders
WHERE customer_id = %d",
$user->ID
),
ARRAY_A
);
} else {
$orders = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
"SELECT p.post_date AS created_date,
pm.post_id
FROM {$wpdb->posts} AS p
LEFT JOIN {$wpdb->postmeta} AS pm
ON ( p.ID = pm.post_id AND p.post_type = %s )
WHERE pm.meta_key = %s
AND pm.meta_value = %d",
'shop_order',
'_customer_user',
$user->ID
),
ARRAY_A
);
}
wp_cache_set( 'wc_sc_order_by_email_for_' . $user->ID, $orders, 'woocommerce_smart_coupons' );
$this->maybe_add_cache_key( 'wc_sc_order_by_email_for_' . $user->ID );
}
$done = false;
$items_removed = false;
$items_retained = false;
$messages = array();
if ( ! empty( $orders ) ) {
foreach ( $orders as $order ) {
list( $removed, $retained, $msgs ) = $this->maybe_handle_order_data( $order );
$items_removed |= $removed;
$items_retained |= $retained;
$messages = array_merge( $messages, $msgs );
}
}
// Tell core if we have more coupons to work on still.
$done = count( $orders ) < 10;
return array(
'items_removed' => $items_removed,
'items_retained' => $items_retained,
'messages' => $messages,
'done' => $done,
);
}
/**
* Handle eraser of Coupon data
*
* @param array $order The order data.
* @return array
*/
protected function maybe_handle_order_data( $order ) {
if ( empty( $order ) || ! $this->is_retention_expired( $order['created_date'] ) ) {
return array( false, false, array() );
}
$order = ( ! empty( $order['post_id'] ) && function_exists( 'wc_get_order' ) ) ? wc_get_order( $order['post_id'] ) : null;
if ( $this->is_callable( $order, 'delete_meta_data' ) && $this->is_callable( $order, 'save' ) ) {
$order->delete_meta_data( 'sc_coupon_receiver_details' );
$order->delete_meta_data( 'gift_receiver_email' );
$order->delete_meta_data( 'gift_receiver_message' );
$order->delete_meta_data( 'gift_sending_timestamp' );
$order->save();
} else {
delete_post_meta( $order['post_id'], 'sc_coupon_receiver_details' );
delete_post_meta( $order['post_id'], 'gift_receiver_email' );
delete_post_meta( $order['post_id'], 'gift_receiver_message' );
delete_post_meta( $order['post_id'], 'gift_sending_timestamp' );
}
return array( true, false, array( '<strong>' . __( 'Store Credit/Gift Certificate', 'woocommerce-smart-coupons' ) . '</strong> - ' . __( 'Removed Order Personal Data', 'woocommerce-smart-coupons' ) ) );
}
/**
* Remove Smart Coupons order personal data
*
* @param WC_Order $order The order object.
*/
public function remove_order_personal_data( $order ) {
$created_date = $order->get_date_created();
$args = array(
'post_id' => $order->get_id(),
'created_date' => $created_date,
);
$result = $this->maybe_handle_order_data( $args );
}
/**
* Checks if create date is passed retention duration.
*
* @param string $created_date The date.
*/
public function is_retention_expired( $created_date ) {
$retention = wc_parse_relative_date_option( get_option( 'woocommerce_smart_coupons_retention' ) );
$is_expired = false;
$time_span = time() - $this->strtotime( $created_date );
if ( empty( $retention ) || empty( $created_date ) || ! isset( $retention['number'] ) || ! isset( $retention['unit'] ) ) {
return false;
}
if ( empty( $retention['number'] ) || ! is_scalar( $retention['number'] ) ) {
return false;
}
if ( ! is_int( $retention['number'] ) ) {
$retention['number'] = (int) $retention['number'];
}
switch ( $retention['unit'] ) {
case 'days':
$retention = $retention['number'] * DAY_IN_SECONDS;
if ( $time_span > $retention ) {
$is_expired = true;
}
break;
case 'weeks':
$retention = $retention['number'] * WEEK_IN_SECONDS;
if ( $time_span > $retention ) {
$is_expired = true;
}
break;
case 'months':
$retention = $retention['number'] * MONTH_IN_SECONDS;
if ( $time_span > $retention ) {
$is_expired = true;
}
break;
case 'years':
$retention = $retention['number'] * YEAR_IN_SECONDS;
if ( $time_span > $retention ) {
$is_expired = true;
}
break;
}
return $is_expired;
}
/**
* Add retention settings to account tab.
*
* @param array $settings Settings.
* @return array $settings Updated
*/
public function account_settings( $settings ) {
$insert_setting = array(
array(
'title' => __( 'Retain Store Credit/Gift Certificate', 'woocommerce-smart-coupons' ),
'desc_tip' => __( 'Store Credit/Gift Certificate that are stored for customers via coupons. If erased, the customer will not be able to use the coupons.', 'woocommerce-smart-coupons' ),
'id' => 'woocommerce_smart_coupons_retention',
'type' => 'relative_date_selector',
'placeholder' => __( 'N/A', 'woocommerce-smart-coupons' ),
'default' => '',
'autoload' => false,
),
);
array_splice( $settings, ( count( $settings ) - 1 ), 0, $insert_setting );
return $settings;
}
}
}
WC_SC_Privacy::get_instance();

View File

@@ -0,0 +1,258 @@
<?php
/**
* Class to show related coupons on a product page.
*
* @package woocommerce-smart-coupons/includes/
* @author StoreApps
* @since 7.12.0
* @version 1.0.0
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WC_SC_Product_Columns' ) ) {
/**
* Class for handling product columns
*/
class WC_SC_Product_Columns {
/**
* Variable to hold instance of WC_SC_Product_Columns
*
* @var $instance
*/
private static $instance = null;
/**
* Post type.
*
* @var string
*/
protected $list_table_type = 'product';
/**
* Object being shown on the row.
*
* @var object|null
*/
protected $object = null;
/**
* Constructor
*/
private function __construct() {
add_filter( 'manage_' . $this->list_table_type . '_posts_columns', array( $this, 'define_columns' ), 11 );
add_action( 'manage_' . $this->list_table_type . '_posts_custom_column', array( $this, 'render_columns' ), 10, 2 );
}
/**
* Get single instance of WC_SC_Product_Columns
*
* @return WC_SC_Product_Columns Singleton object of WC_SC_Product_Columns
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Define which columns to show on this screen.
*
* @param array $columns Existing columns.
* @return array Updated columns list.
*/
public function define_columns( $columns = array() ) {
if ( ! is_array( $columns ) || empty( $columns ) ) {
$columns = array();
}
$columns['wc_sc_linked_coupons'] = _x( 'Linked coupons', 'Title for coupon column on the products page', 'woocommerce-smart-coupons' );
return $columns;
}
/**
* Pre-fetch any data for the row each column has access to it.
*
* @param int $post_id Post ID being shown.
*/
protected function prepare_row_data( $post_id = 0 ) {
if ( empty( $post_id ) ) {
return;
}
$product_id = 0;
if ( ! empty( $this->object ) ) {
$product = $this->object;
if ( $this->is_wc_gte_30() ) {
$product_id = ( is_object( $product ) && is_callable( array( $product, 'get_id' ) ) ) ? $product->get_id() : 0;
} else {
$product_id = ( ! empty( $product->id ) ) ? $product->id : 0;
}
}
if ( empty( $this->object ) || $product_id !== $post_id ) {
$this->object = wc_get_product( $post_id );
}
}
/**
* Render individual columns.
*
* @param string $column Column ID to render.
* @param integer $post_id Post ID being shown.
*/
public function render_columns( $column = '', $post_id = 0 ) {
if ( empty( $post_id ) ) {
return;
}
if ( empty( $column ) ) {
return;
}
$this->prepare_row_data( $post_id );
switch ( $column ) {
case 'wc_sc_linked_coupons':
$this->render_view_product_coupon_column( $post_id, $this->object );
break;
}
}
/**
* Render linked coupons column on product screen.
*
* @param integer $product_id The Product ID.
* @param WC_Product $product The Product object.
*/
public function render_view_product_coupon_column( $product_id = 0, $product = null ) {
if ( empty( $product_id ) ) {
return;
}
$max_coupons_limit = apply_filters(
'wc_sc_maximum_linked_coupons_limit',
$this->sc_get_option( 'wc_sc_maximum_linked_coupons_limit', 5 ),
array(
'source' => $this,
'product_id' => $product_id,
'product_obj' => $product,
)
);
// Fetch linked coupons from simple & variable products (except variations).
$linked_coupons = ( $this->is_callable( $product, 'get_meta' ) ) ? $product->get_meta( '_coupon_title' ) : $this->get_post_meta( $product_id, '_coupon_title', true );
if ( empty( $linked_coupons ) || ! is_array( $linked_coupons ) ) {
$linked_coupons = array();
} else {
$linked_coupons = array_filter( array_unique( $linked_coupons ) );
}
$linked_coupons_count = count( $linked_coupons );
if ( $linked_coupons_count > $max_coupons_limit ) {
$linked_coupons = array_slice( $linked_coupons, 0, $max_coupons_limit );
} elseif ( $linked_coupons_count < $max_coupons_limit ) { // Try to find more linked coupons if number of found coupons are not matching $max_coupons_limit.
// Try to find linked coupons from the variations.
if ( $product->is_type( 'variable' ) && $product->has_child() ) {
$children = $product->get_children();
foreach ( $children as $variation_id ) {
$variation = wc_get_product( $variation_id );
$variation_linked_coupons = ( $this->is_callable( $variation, 'get_meta' ) ) ? $variation->get_meta( '_coupon_title' ) : $this->get_post_meta( $variation_id, '_coupon_title', true );
if ( empty( $variation_linked_coupons ) || ! is_array( $variation_linked_coupons ) ) {
continue;
}
$linked_coupons = array_merge( $linked_coupons, $variation_linked_coupons );
$linked_coupons = array_filter( array_unique( $linked_coupons ) );
$linked_coupons_count = count( $linked_coupons );
if ( $linked_coupons_count === $max_coupons_limit ) {
break;
} elseif ( $linked_coupons_count > $max_coupons_limit ) {
$linked_coupons = array_slice( $linked_coupons, 0, $max_coupons_limit );
break;
}
}
}
}
if ( empty( $linked_coupons ) || ! is_array( $linked_coupons ) ) {
echo esc_html( '&ndash;' );
return;
}
$linked_coupons = array_values( $linked_coupons );
$coupon_html = array();
foreach ( $linked_coupons as $index => $coupon_code ) {
$coupon_id = wc_get_coupon_id_by_code( $coupon_code );
$coupon_edit_url = add_query_arg(
array(
'post' => $coupon_id,
'action' => 'edit',
),
admin_url( 'post.php' )
);
$coupon_html[] = '<a href="' . esc_url( $coupon_edit_url ) . '" target="_blank" title="' . esc_attr__( 'Open in a new tab', 'woocommerce-smart-coupons' ) . '"><code>' . esc_html( $coupon_code ) . '</code></a>';
}
$linked_coupons_html = apply_filters(
'wc_sc_product_column_linked_coupons_html',
implode( ' , ', $coupon_html ),
array(
'source' => $this,
'product_id' => $product_id,
'product_obj' => $product,
'maximum_linked_coupons_limit' => $max_coupons_limit,
'linked_coupons' => $linked_coupons,
)
);
echo wp_kses_post( $linked_coupons_html );
}
}
}
WC_SC_Product_Columns::get_instance();

View File

@@ -0,0 +1,524 @@
<?php
/**
* Smart Coupons fields in products
*
* @author StoreApps
* @since 3.3.0
* @version 1.4.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Product_Fields' ) ) {
/**
* Class for handling Smart Coupons' field in products
*/
class WC_SC_Product_Fields {
/**
* Variable to hold instance of WC_SC_Product_Fields
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'woocommerce_product_options_general_product_data', array( $this, 'woocommerce_product_options_coupons' ) );
add_action( 'woocommerce_product_after_variable_attributes', array( $this, 'woocommerce_product_options_coupons_variable' ), 10, 3 );
add_action( 'woocommerce_process_product_meta', array( $this, 'woocommerce_process_product_meta_coupons' ), 10, 2 );
add_action( 'woocommerce_save_product_variation', array( $this, 'woocommerce_process_product_meta_coupons_variable' ), 10, 2 );
}
/**
* Get single instance of WC_SC_Product_Fields
*
* @return WC_SC_Product_Fields Singleton object of WC_SC_Product_Fields
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Function to provide area for entering coupon code
*/
public function woocommerce_product_options_coupons() {
global $post;
$product_type = WC_Product_Factory::get_product_type( $post->ID );
$product = ( ! empty( $post->ID ) && function_exists( 'wc_get_product' ) ) ? wc_get_product( $post->ID ) : null;
$is_callable_product_get_meta = $this->is_callable( $product, 'get_meta' );
$is_send_coupons_on_renewals = ( true === $is_callable_product_get_meta ) ? $product->get_meta( 'send_coupons_on_renewals' ) : get_post_meta( $post->ID, 'send_coupons_on_renewals', true );
echo '<div class="options_group smart-coupons-field">';
$all_discount_types = wc_get_coupon_types();
?>
<p class="form-field smart-coupon-search post_<?php echo esc_attr( $post->ID ); ?>">
<label for="_coupon_title"><?php echo esc_html__( 'Coupons', 'woocommerce-smart-coupons' ); ?></label>
<select class="wc-coupon-search" style="width: 50%;" multiple="multiple" id="_coupon_title_<?php echo esc_attr( $post->ID ); ?>" name="_coupon_title[<?php echo esc_attr( $post->ID ); ?>][]" data-placeholder="<?php echo esc_attr__( 'Search for a coupon&hellip;', 'woocommerce-smart-coupons' ); ?>" data-action="sc_json_search_coupons" data-security="<?php echo esc_attr( wp_create_nonce( 'search-coupons' ) ); ?>" >
<?php
$coupon_titles = ( true === $is_callable_product_get_meta ) ? $product->get_meta( '_coupon_title' ) : get_post_meta( $post->ID, '_coupon_title', true );
if ( ! empty( $coupon_titles ) ) {
foreach ( $coupon_titles as $coupon_title ) {
$coupon = new WC_Coupon( $coupon_title );
$discount_type = $coupon->get_discount_type();
if ( ! empty( $discount_type ) ) {
/* translators: 1. Discount type 2. Discount Type Label */
$discount_type = sprintf( __( ' ( %1$s: %2$s )', 'woocommerce-smart-coupons' ), __( 'Type', 'woocommerce-smart-coupons' ), $all_discount_types[ $discount_type ] );
}
echo '<option value="' . esc_attr( $coupon_title ) . '"' . selected( true, true, false ) . '>' . esc_html( $coupon_title . $discount_type ) . '</option>';
}
}
?>
</select>
<?php
echo wc_help_tip( esc_html__( 'These coupon/s will be given to customers who buy this product. The coupon code will be automatically sent to their email address on purchase.', 'woocommerce-smart-coupons' ) ); // phpcs:ignore
?>
</p>
<p class="form-field send_coupons_on_renewals_field post_<?php echo esc_attr( $post->ID ); ?>" style="display: none;">
<label for="send_coupons_on_renewals"><?php echo esc_html__( 'Send coupons on renewals?', 'woocommerce-smart-coupons' ); ?></label>
<input type="checkbox" class="checkbox" style="" name="send_coupons_on_renewals[<?php echo esc_attr( $post->ID ); ?>]" id="send_coupons_on_renewals_<?php echo esc_attr( $post->ID ); ?>" value="yes" <?php checked( $is_send_coupons_on_renewals, 'yes' ); ?>/>
<?php echo wc_help_tip( esc_html__( 'Check this box to send above coupons on each renewal order.', 'woocommerce-smart-coupons' ) ); // phpcs:ignore ?>
</p>
<?php $this->product_options_admin_js(); ?>
<?php
echo '</div>';
}
/**
* Coupon fields for variation
*
* @param int $loop Position in the loop.
* @param array $variation_data Variation data.
* @param WP_Post $variation Post data.
*/
public function woocommerce_product_options_coupons_variable( $loop = 0, $variation_data = array(), $variation = null ) {
$variation_id = $variation->ID;
$all_discount_types = wc_get_coupon_types();
$product = ( ! empty( $variation_id ) && function_exists( 'wc_get_product' ) ) ? wc_get_product( $variation_id ) : null;
$is_callable_product_get_meta = $this->is_callable( $product, 'get_meta' );
$is_send_coupons_on_renewals = ( true === $is_callable_product_get_meta ) ? $product->get_meta( 'send_coupons_on_renewals' ) : get_post_meta( $variation_id, 'send_coupons_on_renewals', true );
?>
<div class="smart_coupons_product_options_variable smart-coupons-field">
<p class="form-field smart-coupon-search _coupon_title_field post_<?php echo esc_attr( $variation_id ); ?> form-row form-row-full">
<label for="_coupon_title_<?php echo esc_attr( $loop ); ?>"><?php echo esc_html__( 'Coupons', 'woocommerce-smart-coupons' ); ?></label>
<?php echo wc_help_tip( esc_html__( 'These coupon/s will be given to customers who buy this product. The coupon code will be automatically sent to their email address on purchase.', 'woocommerce-smart-coupons' ) ); // phpcs:ignore ?>
<select class="wc-coupon-search" style="width: 100% !important;" multiple="multiple" id="_coupon_title_<?php echo esc_attr( $variation_id ); ?>" name="_coupon_title[<?php echo esc_attr( $variation_id ); ?>][<?php echo esc_attr( $loop ); ?>][]" data-placeholder="<?php echo esc_attr__( 'Search for a coupon&hellip;', 'woocommerce-smart-coupons' ); ?>" data-action="sc_json_search_coupons" data-security="<?php echo esc_attr( wp_create_nonce( 'search-coupons' ) ); ?>" >
<?php
$coupon_titles = ( true === $is_callable_product_get_meta ) ? $product->get_meta( '_coupon_title' ) : get_post_meta( $variation_id, '_coupon_title', true );
if ( ! empty( $coupon_titles ) ) {
foreach ( $coupon_titles as $coupon_title ) {
$coupon = new WC_Coupon( $coupon_title );
$discount_type = $coupon->get_discount_type();
if ( ! empty( $discount_type ) ) {
/* translators: 1. Discount type 2. Discount Type Label */
$discount_type = sprintf( __( ' ( %1$s: %2$s )', 'woocommerce-smart-coupons' ), __( 'Type', 'woocommerce-smart-coupons' ), $all_discount_types[ $discount_type ] );
}
echo '<option value="' . esc_attr( $coupon_title ) . '"' . selected( true, true, false ) . '>' . esc_html( $coupon_title . $discount_type ) . '</option>';
}
}
?>
</select>
</p>
<p class="form-field send_coupons_on_renewals_field post_<?php echo esc_attr( $variation_id ); ?> form-row form-row-full">
<label class="tips" data-tip="<?php echo esc_attr__( 'Check this box to send above coupons on each renewal order.', 'woocommerce-smart-coupons' ); ?>">
<?php echo esc_html__( 'Send coupons on renewals?', 'woocommerce-smart-coupons' ); ?>
<input type="checkbox" class="checkbox" id="send_coupons_on_renewals_<?php echo esc_attr( $variation_id ); ?>" name="send_coupons_on_renewals[<?php echo esc_attr( $variation_id ); ?>][<?php echo esc_attr( $loop ); ?>]" style="margin: 0.1em 0.5em 0.1em 0 !important;" value="yes" <?php checked( $is_send_coupons_on_renewals, 'yes' ); ?>/>
</label>
</p>
<?php $this->product_options_admin_js(); ?>
</div>
<?php
}
/**
* Product options admin JS
*/
public function product_options_admin_js() {
?>
<script type="text/javascript">
jQuery(function(){
var updateSendCouponOnRenewals = function(theElement) {
let element;
if (typeof theElement == "undefined") {
element = jQuery('.smart-coupons-field');
} else {
element = [theElement];
}
jQuery.each(element, function(index, value){
var prodType = jQuery('select#product-type').find('option:selected').val();
<?php if ( $this->is_wc_gte_30() ) { ?>
var associatedCouponCount = jQuery(value).find('.smart-coupon-search span.select2-selection ul.select2-selection__rendered li.select2-selection__choice').length;
<?php } else { ?>
var associatedCouponCount = jQuery(value).find('.smart-coupon-search ul.select2-choices li.select2-search-choice').length;
<?php } ?>
if ( ( prodType == 'subscription' || prodType == 'variable-subscription' || prodType == 'subscription_variation' ) && associatedCouponCount > 0 ) {
jQuery(value).find('p.send_coupons_on_renewals_field').show();
} else {
jQuery(value).find('p.send_coupons_on_renewals_field').hide();
}
});
};
setTimeout(function(){updateSendCouponOnRenewals();}, 100);
jQuery('select#product-type').on('change', function() {
var productType = jQuery(this).find('option:selected').val();
if ( productType == 'simple' || productType == 'variable' || productType == 'subscription' || productType == 'variable-subscription' || productType == 'subscription_variation' ) {
jQuery('.wc-coupon-search').show();
} else {
jQuery('.wc-coupon-search').hide();
}
updateSendCouponOnRenewals();
});
jQuery('.wc-coupon-search').on('change', function(){
let theElement = jQuery(this).parent().parent();
setTimeout( function() {
updateSendCouponOnRenewals(theElement);
}, 10 );
});
if ( typeof getEnhancedSelectFormatString == "undefined" ) {
function getEnhancedSelectFormatString() {
var formatString = {
formatMatches: function( matches ) {
if ( 1 === matches ) {
return smart_coupons_select_params.i18n_matches_1;
}
return smart_coupons_select_params.i18n_matches_n.replace( '%qty%', matches );
},
formatNoMatches: function() {
return smart_coupons_select_params.i18n_no_matches;
},
formatAjaxError: function( jqXHR, textStatus, errorThrown ) {
return smart_coupons_select_params.i18n_ajax_error;
},
formatInputTooShort: function( input, min ) {
var number = min - input.length;
if ( 1 === number ) {
return smart_coupons_select_params.i18n_input_too_short_1
}
return smart_coupons_select_params.i18n_input_too_short_n.replace( '%qty%', number );
},
formatInputTooLong: function( input, max ) {
var number = input.length - max;
if ( 1 === number ) {
return smart_coupons_select_params.i18n_input_too_long_1
}
return smart_coupons_select_params.i18n_input_too_long_n.replace( '%qty%', number );
},
formatSelectionTooBig: function( limit ) {
if ( 1 === limit ) {
return smart_coupons_select_params.i18n_selection_too_long_1;
}
return smart_coupons_select_params.i18n_selection_too_long_n.replace( '%qty%', number );
},
formatLoadMore: function( pageNumber ) {
return smart_coupons_select_params.i18n_load_more;
},
formatSearching: function() {
return smart_coupons_select_params.i18n_searching;
}
};
return formatString;
}
}
<?php if ( $this->is_wc_gte_30() ) { // Ajax product search box. ?>
jQuery( '[class= "wc-coupon-search"]' ).filter( ':not(.enhanced)' ).each( function() {
var select2_args = {
allowClear: jQuery( this ).data( 'allow_clear' ) ? true : false,
placeholder: jQuery( this ).data( 'placeholder' ),
minimumInputLength: jQuery( this ).data( 'minimum_input_length' ) ? jQuery( this ).data( 'minimum_input_length' ) : '3',
escapeMarkup: function( m ) {
return m;
},
ajax: {
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
dataType: 'json',
quietMillis: 250,
data: function( params, page ) {
return {
term: params.term,
action: jQuery( this ).data( 'action' ) || 'sc_json_search_coupons',
security: jQuery( this ).data( 'security' )
};
},
processResults: function( data, page ) {
var terms = [];
if ( data ) {
jQuery.each( data, function( id, text ) {
terms.push( { id: id, text: text } );
});
}
return { results: terms };
},
cache: true
}
};
select2_args = jQuery.extend( select2_args, getEnhancedSelectFormatString() );
jQuery( this ).select2( select2_args );
});
<?php } else { ?>
jQuery( ':input.wc-coupon-search' ).filter( ':not(.enhanced)' ).each( function() {
var select2_args = {
allowClear: jQuery( this ).data( 'allow_clear' ) ? true : false,
placeholder: jQuery( this ).data( 'placeholder' ),
minimumInputLength: jQuery( this ).data( 'minimum_input_length' ) ? jQuery( this ).data( 'minimum_input_length' ) : '3',
escapeMarkup: function( m ) {
return m;
},
ajax: {
url: decodeURIComponent( '<?php echo rawurlencode( admin_url( 'admin-ajax.php' ) ); ?>' ),
dataType: 'json',
quietMillis: 250,
data: function( term, page ) {
return {
term: term,
action: jQuery( this ).data( 'action' ) || 'sc_json_search_coupons',
security: '<?php echo esc_attr( wp_create_nonce( 'search-coupons' ) ); ?>'
};
},
results: function( data, page ) {
var terms = [];
if ( data ) {
jQuery.each( data, function( id, text ) {
terms.push( { id: id, text: text } );
});
}
return { results: terms };
},
cache: true
}
};
if ( jQuery( this ).data( 'multiple' ) === true ) {
select2_args.multiple = true;
select2_args.initSelection = function( element, callback ) {
var data = jQuery.parseJSON( element.attr( 'data-selected' ) );
var selected = [];
jQuery( element.val().split( "," ) ).each( function( i, val ) {
selected.push( { id: val, text: data[ val ] } );
});
return callback( selected );
};
select2_args.formatSelection = function( data ) {
return '<div class="selected-option" data-id="' + data.id + '">' + data.text + '</div>';
};
} else {
select2_args.multiple = false;
select2_args.initSelection = function( element, callback ) {
var data = {id: element.val(), text: element.attr( 'data-selected' )};
return callback( data );
};
}
select2_args = jQuery.extend( select2_args, getEnhancedSelectFormatString() );
jQuery( this ).select2( select2_args ).addClass( 'enhanced' );
});
<?php } ?>
});
</script>
<?php
}
/**
* Function to save coupon code to database
*
* @param int $post_id The post id.
* @param object $post The post object.
*/
public function woocommerce_process_product_meta_coupons( $post_id = 0, $post = null ) {
$post_id = absint( $post_id );
$post_coupon_title = ( ! empty( $_POST['_coupon_title'][ $post_id ] ) ) ? wc_clean( wp_unslash( $_POST['_coupon_title'][ $post_id ] ) ) : ''; // phpcs:ignore
$product = ( ! empty( $post_id ) ) ? wc_get_product( $post_id ) : null;
$is_callable_product_update_meta = $this->is_callable( $product, 'update_meta_data' );
if ( ! empty( $post_coupon_title ) ) {
if ( $this->is_wc_gte_30() ) {
$coupon_titles = $post_coupon_title;
} else {
$coupon_titles = array_filter( array_map( 'trim', explode( ',', $post_coupon_title ) ) );
}
if ( true === $is_callable_product_update_meta ) {
$product->update_meta_data( '_coupon_title', $coupon_titles );
} else {
update_post_meta( $post_id, '_coupon_title', $coupon_titles );
}
} else {
if ( true === $is_callable_product_update_meta ) {
$product->update_meta_data( '_coupon_title', array() );
} else {
update_post_meta( $post_id, '_coupon_title', array() );
}
}
if ( isset( $_POST['send_coupons_on_renewals'][ $post_id ] ) ) { // phpcs:ignore
if ( true === $is_callable_product_update_meta ) {
$product->update_meta_data( 'send_coupons_on_renewals', wc_clean( wp_unslash( $_POST['send_coupons_on_renewals'][ $post_id ] ) ) ); // phpcs:ignore
} else {
update_post_meta( $post_id, 'send_coupons_on_renewals', wc_clean( wp_unslash( $_POST['send_coupons_on_renewals'][ $post_id ] ) ) ); // phpcs:ignore
}
} else {
if ( true === $is_callable_product_update_meta ) {
$product->update_meta_data( 'send_coupons_on_renewals', 'no' );
} else {
update_post_meta( $post_id, 'send_coupons_on_renewals', 'no' );
}
}
if ( $this->is_callable( $product, 'save' ) ) {
$product->save();
}
}
/**
* Function for saving coupon details in product meta
*
* @param integer $variation_id Variation ID.
* @param integer $i Loop ID.
*/
public function woocommerce_process_product_meta_coupons_variable( $variation_id = 0, $i = 0 ) {
if ( empty( $variation_id ) ) {
return;
}
$variation_id = absint( $variation_id );
$variation = ( ! empty( $variation_id ) ) ? wc_get_product( $variation_id ) : null;
$is_callable_variation_update_meta = $this->is_callable( $variation, 'update_meta_data' );
$post_coupon_title = ( ! empty( $_POST['_coupon_title'][ $variation_id ][ $i ] ) ) ? wc_clean( wp_unslash( $_POST['_coupon_title'][ $variation_id ][ $i ] ) ) : ''; // phpcs:ignore
if ( ! empty( $post_coupon_title ) ) {
if ( $this->is_wc_gte_30() ) {
$coupon_titles = $post_coupon_title;
} else {
$coupon_titles = array_filter( array_map( 'trim', explode( ',', $post_coupon_title ) ) );
}
if ( true === $is_callable_variation_update_meta ) {
$variation->update_meta_data( '_coupon_title', $coupon_titles );
} else {
update_post_meta( $variation_id, '_coupon_title', $coupon_titles );
}
} else {
if ( true === $is_callable_variation_update_meta ) {
$variation->update_meta_data( '_coupon_title', array() );
} else {
update_post_meta( $variation_id, '_coupon_title', array() );
}
}
if ( isset( $_POST['send_coupons_on_renewals'][ $variation_id ][ $i ] ) ) { // phpcs:ignore
if ( true === $is_callable_variation_update_meta ) {
$variation->update_meta_data( 'send_coupons_on_renewals', wc_clean( wp_unslash( $_POST['send_coupons_on_renewals'][ $variation_id ][ $i ] ) ) ); // phpcs:ignore
} else {
update_post_meta( $variation_id, 'send_coupons_on_renewals', wc_clean( wp_unslash( $_POST['send_coupons_on_renewals'][ $variation_id ][ $i ] ) ) ); // phpcs:ignore
}
} else {
if ( true === $is_callable_variation_update_meta ) {
$variation->update_meta_data( 'send_coupons_on_renewals', 'no' );
} else {
update_post_meta( $variation_id, 'send_coupons_on_renewals', 'no' );
}
}
if ( $this->is_callable( $variation, 'save' ) ) {
$variation->save();
}
}
}
}
WC_SC_Product_Fields::get_instance();

View File

@@ -0,0 +1,236 @@
<?php
/**
* REST API Coupons controller for Smart Coupons
*
* Handles requests to the wc/sc/v1/coupons endpoint.
*
* @author StoreApps
* @since 4.10.0
* @version 1.2.0
*
* @package woocommerce-smart-coupons/includes/
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'WC_SC_REST_Coupons_Controller' ) ) {
/**
* REST API Coupons controller class.
*
* @package Automattic/WooCommerce/RestApi
* @extends WC_REST_CRUD_Controller
*/
class WC_SC_REST_Coupons_Controller extends WC_REST_Coupons_Controller {
/**
* Endpoint namespace.
*
* @var string
*/
protected $namespace = 'wc/v3/sc';
/**
* Route base.
*
* @var string
*/
protected $rest_base = 'coupons';
/**
* Post type.
*
* @var string
*/
protected $post_type = 'shop_coupon';
/**
* Constructor
*/
public function __construct() {
add_filter( "woocommerce_rest_prepare_{$this->post_type}_object", array( $this, 'handle_response_data' ), 99, 3 );
}
/**
* Register the routes for coupons.
*/
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
array(
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'create_item' ),
'permission_callback' => array( $this, 'create_item_permissions_check' ),
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
),
'schema' => array( $this, 'get_public_item_schema' ),
)
);
}
/**
* Prepare a single coupon for create or update.
*
* @param WP_REST_Request $request Request object.
* @param bool $creating If is creating a new object.
* @return WP_Error|WC_Data
*/
protected function prepare_object_for_database( $request, $creating = false ) {
global $woocommerce_smart_coupon;
$id = isset( $request['id'] ) ? absint( $request['id'] ) : 0;
$coupon = new WC_Coupon( $id );
$schema = $this->get_item_schema();
$data_keys = array_keys( array_filter( $schema['properties'], array( $this, 'filter_writable_props' ) ) );
$email_restrictions = ( ! empty( $request['email_restrictions'] ) && count( $request['email_restrictions'] ) === 1 ) ? $request['email_restrictions'] : '';
// Validate required POST fields.
if ( $creating ) {
if ( empty( $request['code'] ) ) {
$request['code'] = $woocommerce_smart_coupon->generate_unique_code( $email_restrictions );
} else {
$_coupon = new WC_Coupon( $request['code'] );
$is_auto_generate = ( is_object( $_coupon ) && is_callable( array( $_coupon, 'get_meta' ) ) ) ? $_coupon->get_meta( 'auto_generate_coupon' ) : 'no';
if ( 'yes' === $is_auto_generate ) {
$request['code'] = $woocommerce_smart_coupon->generate_unique_code( $email_restrictions );
foreach ( $data_keys as $key ) {
if ( empty( $request[ $key ] ) ) {
switch ( $key ) {
case 'code':
// do nothing.
break;
case 'meta_data':
$meta_data = ( is_object( $_coupon ) && is_callable( array( $_coupon, 'get_meta_data' ) ) ) ? $_coupon->get_meta_data() : null;
$new_meta_data = array();
if ( ! empty( $meta_data ) ) {
foreach ( $meta_data as $meta ) {
if ( is_object( $meta ) && is_callable( array( $meta, 'get_data' ) ) ) {
$data = $meta->get_data();
if ( isset( $data['id'] ) ) {
unset( $data['id'] );
}
$new_meta_data[] = $data;
}
}
}
$request[ $key ] = $new_meta_data;
break;
case 'description':
$request[ $key ] = ( is_object( $_coupon ) && is_callable( array( $_coupon, 'get_description' ) ) ) ? $_coupon->get_description() : null;
break;
default:
if ( is_callable( array( $_coupon, "get_{$key}" ) ) ) {
$request[ $key ] = $_coupon->{"get_{$key}"}();
}
break;
}
}
}
}
}
}
// Handle all writable props.
foreach ( $data_keys as $key ) {
$value = $request[ $key ];
if ( ! is_null( $value ) ) {
switch ( $key ) {
case 'code':
$coupon_code = wc_format_coupon_code( $value );
$id = $coupon->get_id() ? $coupon->get_id() : 0;
$id_from_code = wc_get_coupon_id_by_code( $coupon_code, $id );
if ( $id_from_code ) {
return new WP_Error( 'woocommerce_rest_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce-smart-coupons' ), array( 'status' => 400 ) );
}
$coupon->set_code( $coupon_code );
break;
case 'meta_data':
if ( is_array( $value ) ) {
foreach ( $value as $meta ) {
$coupon->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' );
}
}
break;
case 'description':
$coupon->set_description( wp_filter_post_kses( $value ) );
break;
default:
if ( is_callable( array( $coupon, "set_{$key}" ) ) ) {
$coupon->{"set_{$key}"}( $value );
}
break;
}
}
}
/**
* Filters an object before it is inserted via the REST API.
*
* The dynamic portion of the hook name, `$this->post_type`,
* refers to the object type slug.
*
* @param WC_Data $coupon Object object.
* @param WP_REST_Request $request Request object.
* @param bool $creating If is creating a new object.
*/
return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}_object", $coupon, $request, $creating );
}
/**
* Handle REST response data
*
* @param WP_REST_Response|mixed $response The response.
* @param WC_Coupon|mixed $object The object.
* @param WP_REST_Request|mixed $request The request.
* @return WP_REST_Response
*/
public function handle_response_data( $response = null, $object = null, $request = null ) {
global $woocommerce_smart_coupon;
if ( ! empty( $request['sc_is_send_email'] ) && 'yes' === $request['sc_is_send_email'] ) {
$is_send_email = $woocommerce_smart_coupon->is_email_template_enabled();
$email_restrictions = ( ! empty( $request['email_restrictions'] ) ) ? current( $request['email_restrictions'] ) : '';
if ( 'yes' === $is_send_email && ! empty( $email_restrictions ) ) {
$coupon = array(
'code' => ( is_object( $object ) && is_callable( array( $object, 'get_code' ) ) ) ? $object->get_code() : '',
'amount' => ( is_object( $object ) && is_callable( array( $object, 'get_amount' ) ) ) ? $object->get_amount() : 0,
);
$action_args = apply_filters(
'wc_sc_email_coupon_notification_args',
array(
'email' => $email_restrictions,
'coupon' => $coupon,
'discount_type' => ( is_object( $object ) && is_callable( array( $object, 'get_discount_type' ) ) ) ? $object->get_discount_type() : '',
)
);
// Trigger email notification.
do_action( 'wc_sc_email_coupon_notification', $action_args );
}
}
if ( ! empty( $request['sc_is_html'] ) && 'yes' === $request['sc_is_html'] ) {
$data = '';
ob_start();
do_action(
'wc_sc_paint_coupon',
array(
'coupon' => $object,
'with_css' => 'yes',
'with_container' => 'yes',
)
);
$data = ob_get_clean();
$response = rest_ensure_response( $data );
}
return $response;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,970 @@
<?php
/**
* Smart Coupons Shortcode
*
* @author StoreApps
* @since 3.3.0
* @version 2.9.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Shortcode' ) ) {
/**
* Class for handling Smart Coupons Shortcode
*/
class WC_SC_Shortcode {
/**
* Variable to hold instance of WC_SC_Shortcode
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'smart_coupon_shortcode_button_init' ), 20 ); // Use 'admin_enqueue_scripts' instead of 'init' // Credit: Jonathan Desrosiers <jdesrosiers@linchpinagency.com>.
add_action( 'init', array( $this, 'register_smart_coupon_shortcode' ) );
add_action( 'after_wp_tiny_mce', array( $this, 'smart_coupons_after_wp_tiny_mce' ) );
add_filter( 'wc_sc_available_coupon_ids', array( $this, 'filter_coupon_ids' ), 10, 2 );
}
/**
* Get single instance of WC_SC_Shortcode
*
* @return WC_SC_Shortcode Singleton object of WC_SC_Shortcode
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Add Smart Coupons shortcode button in WP editor
*/
public function smart_coupon_shortcode_button_init() {
if ( get_user_option( 'rich_editing' ) === 'true' && ! current_user_can( 'manage_options' ) ) { // Add shortcode button to WP Editor only when the user is from the top level.
return;
}
if ( ! wp_script_is( 'wpdialogs' ) ) {
wp_enqueue_script( 'wpdialogs' );
}
if ( ! wp_style_is( 'wp-jquery-ui-dialog' ) ) {
wp_enqueue_style( 'wp-jquery-ui-dialog' );
}
if ( ! wp_style_is( 'smart-coupon' ) ) {
wp_enqueue_style( 'smart-coupon' );
}
add_filter( 'mce_external_plugins', array( $this, 'smart_coupon_register_tinymce_plugin' ) );
add_filter( 'mce_buttons', array( $this, 'smart_coupon_add_tinymce_button' ) );
}
/**
* Add Smart Coupon short code button in TinyMCE
*
* @param array $plugin_array Existing plugin.
* @return array $plugin array with SMart Coupon shortcode
*/
public function smart_coupon_register_tinymce_plugin( $plugin_array ) {
$plugin_array['sc_shortcode_button'] = plugins_url( 'assets/js/sc-shortcode.js', WC_SC_PLUGIN_FILE );
return $plugin_array;
}
/**
* Add Smart coupon shortcode button in TinyMCE
*
* @param array $buttons Existing button.
* @return array $buttons With Smart Coupons shortcode button
*/
public function smart_coupon_add_tinymce_button( $buttons ) {
$buttons[] = 'sc_shortcode_button';
return $buttons;
}
/**
* Register shortcode for Smart Coupons
*/
public function register_smart_coupon_shortcode() {
add_shortcode( 'smart_coupons', array( $this, 'execute_smart_coupons_shortcode' ) );
add_shortcode( 'wc_sc_available_coupons', array( $this, 'show_available_coupons_shortcode' ) );
}
/**
* Execute Smart Coupons shortcode
*
* @param array $atts Shortcode attributes.
* @return HTML code for coupon to be displayed
*/
public function execute_smart_coupons_shortcode( $atts ) {
if ( is_admin() || wp_doing_ajax() || WC()->is_rest_api_request() ) {
return;
}
ob_start();
global $wpdb, $store_credit_label;
$current_user = wp_get_current_user();
$customer_id = $current_user->ID;
$shortcode = shortcode_atts(
array(
'coupon_code' => '',
'discount_type' => 'smart_coupon',
'coupon_amount' => '',
'individual_use' => 'no',
'product_ids' => '',
'exclude_product_ids' => '',
'usage_limit' => '',
'usage_limit_per_user' => '',
'limit_usage_to_x_items' => '',
'expiry_date' => '',
'apply_before_tax' => 'no',
'free_shipping' => 'no',
'product_categories' => '',
'exclude_product_categories' => '',
'minimum_amount' => '',
'maximum_amount' => '',
'exclude_sale_items' => 'no',
'auto_generate' => 'no',
'coupon_prefix' => '',
'coupon_suffix' => '',
'customer_email' => '',
'coupon_style' => '',
'disable_email' => 'no',
'expiry_days' => '',
'is_email' => 'no',
'is_clickable' => 'no',
),
$atts
);
$_coupon_code = $shortcode['coupon_code'];
$_discount_type = $shortcode['discount_type'];
$_coupon_amount = $shortcode['coupon_amount'];
$_expiry_date = $shortcode['expiry_date'];
$_free_shipping = $shortcode['free_shipping'];
$customer_email = $shortcode['customer_email'];
$coupon_prefix = $shortcode['coupon_prefix'];
$coupon_suffix = $shortcode['coupon_suffix'];
$individual_use = $shortcode['individual_use'];
$minimum_amount = $shortcode['minimum_amount'];
$maximum_amount = $shortcode['maximum_amount'];
$usage_limit = $shortcode['usage_limit'];
$apply_before_tax = $shortcode['apply_before_tax'];
$disable_email = $shortcode['disable_email'];
$expiry_days = $shortcode['expiry_days'];
$is_email = $shortcode['is_email'];
$is_clickable = $shortcode['is_clickable'];
if ( empty( $_coupon_code ) && empty( $_coupon_amount ) ) {
return; // Minimum requirement for shortcode is either $_coupon_code or $_coupon_amount.
}
if ( empty( $customer_email ) ) {
if ( ! ( $current_user instanceof WP_User ) ) {
$current_user = wp_get_current_user();
$customer_email = ( isset( $current_user->user_email ) ) ? $current_user->user_email : '';
} else {
$customer_email = ( ! empty( $current_user->data->user_email ) ) ? $current_user->data->user_email : '';
}
}
if ( ! empty( $_coupon_code ) && ! empty( $customer_email ) ) {
$coupon_exists = wp_cache_get( 'wc_sc_shortcode_coupon_id_' . sanitize_key( $customer_email ), 'woocommerce_smart_coupons' );
if ( false === $coupon_exists ) {
$coupon_exists = $wpdb->get_var( // phpcs:ignore
$wpdb->prepare(
"SELECT ID
FROM {$wpdb->prefix}posts AS posts
LEFT JOIN {$wpdb->prefix}postmeta AS postmeta
ON ( postmeta.post_id = posts.ID )
WHERE posts.post_title = %s
AND posts.post_type = %s
AND posts.post_status = %s
AND postmeta.meta_key = %s
AND postmeta.meta_value LIKE %s",
strtolower( $_coupon_code ),
'shop_coupon',
'publish',
'customer_email',
'%' . $wpdb->esc_like( '"' . $customer_email . '"' ) . '%'
)
);
wp_cache_set( 'wc_sc_shortcode_coupon_id_' . sanitize_key( $customer_email ), $coupon_exists, 'woocommerce_smart_coupons' );
$this->maybe_add_cache_key( 'wc_sc_shortcode_coupon_id_' . sanitize_key( $customer_email ) );
}
} else {
$coupon_exists = null;
}
$is_generate = apply_filters(
'wc_sc_shortcode_always_generate_coupon',
( null === $coupon_exists ),
array(
'source' => $this,
'shortcode_attributes' => $shortcode,
)
);
$_expiry_date = '';
if ( ! wp_style_is( 'smart-coupon' ) ) {
wp_enqueue_style( 'smart-coupon' );
}
$all_discount_types = wc_get_coupon_types();
if ( true === $is_generate ) {
if ( ! empty( $_coupon_code ) ) {
$coupon = new WC_Coupon( $_coupon_code );
$is_callable_coupon_update_meta = $this->is_callable( $coupon, 'update_meta_data' );
if ( $this->is_wc_gte_30() ) {
if ( ! is_object( $coupon ) || ! is_callable( array( $coupon, 'get_id' ) ) ) {
return;
}
$coupon_id = $coupon->get_id();
if ( empty( $coupon_id ) ) {
return;
}
$is_free_shipping = ( $coupon->get_free_shipping() ) ? 'yes' : 'no';
$discount_type = $coupon->get_discount_type();
$expiry_date = $coupon->get_date_expires();
$coupon_code = $coupon->get_code();
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$is_free_shipping = ( ! empty( $coupon->free_shipping ) ) ? $coupon->free_shipping : '';
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
$expiry_date = ( ! empty( $coupon->expiry_date ) ) ? $coupon->expiry_date : '';
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
$coupon_amount = $this->get_amount( $coupon, true );
$is_callable_coupon_get_meta = $this->is_callable( $coupon, 'get_meta' );
if ( ! empty( $discount_type ) ) {
$is_auto_generate = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'auto_generate_coupon' ) : get_post_meta( $coupon_id, 'auto_generate_coupon', true );
$is_disable_email_restriction = ( true === $is_callable_coupon_get_meta ) ? $coupon->get_meta( 'sc_disable_email_restriction' ) : get_post_meta( $coupon_id, 'sc_disable_email_restriction', true );
if ( ( empty( $is_disable_email_restriction ) || 'no' === $is_disable_email_restriction ) && ( empty( $is_auto_generate ) || 'no' === $is_auto_generate ) ) {
$existing_customer_emails = ( $this->is_callable( $coupon, 'get_email_restrictions' ) ) ? $coupon->get_email_restrictions() : get_post_meta( $coupon_id, 'customer_email', true );
if ( empty( $existing_customer_emails ) || ! is_array( $existing_customer_emails ) ) {
$existing_customer_emails = array();
}
$existing_customer_emails[] = $customer_email;
if ( true === $is_callable_coupon_update_meta ) {
$coupon->set_email_restrictions( $existing_customer_emails );
} else {
update_post_meta( $coupon_id, 'customer_email', $existing_customer_emails );
}
}
if ( ! empty( $is_auto_generate ) && 'yes' === $is_auto_generate ) {
if ( 0 === $current_user->ID ) {
if ( 'smart_coupon' === $discount_type ) {
return; // Don't generate & don't show coupon if coupon of the shortcode is store credit & user is guest, otherwise it'll lead to unlimited generation of coupon.
} else {
$new_generated_coupon_code = $coupon_code;
}
} elseif ( true === $is_generate && 'yes' === $is_email ) {
$generated_coupon_details = $this->generate_smart_coupon_action( $customer_email, $coupon_amount, '', $coupon );
$last_element = end( $generated_coupon_details[ $customer_email ] );
$new_generated_coupon_code = $last_element['code'];
} else {
$shortcode_generated_coupon = $this->get_shortcode_generated_coupon( $current_user, $coupon );
if ( empty( $shortcode_generated_coupon ) || ( true === $is_generate && 'yes' === $is_email ) ) {
$generated_coupon_details = $this->generate_smart_coupon_action( $customer_email, $coupon_amount, '', $coupon );
$last_element = end( $generated_coupon_details[ $customer_email ] );
$new_generated_coupon_code = $last_element['code'];
$this->save_shortcode_generated_coupon( $new_generated_coupon_code, $current_user, $coupon );
} else {
$new_generated_coupon_code = $shortcode_generated_coupon;
}
}
} else {
$new_generated_coupon_code = $_coupon_code;
}
}
}
if ( ( ! empty( $_coupon_code ) && empty( $discount_type ) ) || ( empty( $_coupon_code ) ) ) {
if ( empty( $current_user->ID ) && ( 'smart_coupon' === $_discount_type || 'smart_coupon' === $discount_type ) ) {
return; // It'll prevent generation of unlimited coupons for guest.
}
if ( empty( $coupon ) ) {
$coupon = null;
}
$shortcode_generated_coupon = $this->get_shortcode_generated_coupon( $current_user, $coupon );
if ( empty( $shortcode_generated_coupon ) ) {
if ( empty( $_coupon_code ) ) {
$_coupon_code = $this->generate_unique_code( $customer_email );
$_coupon_code = $coupon_prefix . $_coupon_code . $coupon_suffix;
}
$coupon_args = array(
'post_title' => strtolower( $_coupon_code ),
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon',
'post_parent' => ! empty( $coupon_id ) ? absint( $coupon_id ) : 0,
);
$new_coupon = new WC_Coupon( $coupon_args['post_title'] );
if ( $this->is_wc_greater_than( '6.1.2' ) && $this->is_callable( $new_coupon, 'set_status' ) ) {
$new_coupon->set_status( $coupon_args['post_status'] );
}
$new_coupon_id = $new_coupon->save();
if ( ! empty( $new_coupon_id ) ) {
$coupon_args = array_diff_key( $coupon_args, array_flip( array( 'post_title', 'post_status', 'post_type' ) ) );
$coupon_args['ID'] = $new_coupon_id;
wp_update_post( $coupon_args );
}
$new_coupon_id = absint( $new_coupon_id );
$new_coupon = new WC_Coupon( $new_coupon );
$is_callable_new_coupon_update_meta = $this->is_callable( $new_coupon, 'update_meta_data' );
if ( ! empty( $shortcode['expiry_date'] ) ) {
$timestamp = $this->strtotime( $shortcode['expiry_date'] ) + $this->wc_timezone_offset();
$_expiry_date = gmdate( 'Y-m-d', $timestamp );
} elseif ( ! empty( $expiry_days ) ) {
$timestamp = $this->strtotime( "+$expiry_days days" ) + $this->wc_timezone_offset();
$_expiry_date = gmdate( 'Y-m-d', $timestamp );
}
if ( $this->is_wc_gte_30() ) {
if ( ! empty( $_expiry_date ) ) {
$_expiry_date = $this->strtotime( $_expiry_date ) - $this->wc_timezone_offset();
$_expiry_date = $this->get_date_expires_value( $_expiry_date );
if ( true === $is_callable_new_coupon_update_meta ) {
$new_coupon->set_date_expires( $_expiry_date );
} else {
update_post_meta( $new_coupon_id, 'date_expires', $_expiry_date );
}
}
} else {
if ( true === $is_callable_new_coupon_update_meta ) {
$new_coupon->update_meta_data( 'expiry_date', $_expiry_date );
} else {
update_post_meta( $new_coupon_id, 'expiry_date', $_expiry_date );
}
}
if ( 'smart_coupon' === $_discount_type ) {
$this->update_post_meta( $new_coupon_id, 'wc_sc_original_amount', $_coupon_amount, false );
}
if ( true === $is_callable_new_coupon_update_meta ) {
$new_coupon->set_discount_type( $_discount_type );
$new_coupon->set_amount( $_coupon_amount );
$new_coupon->set_individual_use( $this->wc_string_to_bool( $individual_use ) );
$new_coupon->set_minimum_amount( $minimum_amount );
$new_coupon->set_maximum_amount( $maximum_amount );
$new_coupon->set_usage_limit( $usage_limit );
$new_coupon->set_email_restrictions( array( $customer_email ) );
$new_coupon->update_meta_data( 'apply_before_tax', $apply_before_tax );
$new_coupon->set_free_shipping( $this->wc_string_to_bool( $_free_shipping ) );
$new_coupon->set_product_categories( array() );
$new_coupon->set_excluded_product_categories( array() );
$new_coupon->update_meta_data( 'sc_disable_email_restriction', $disable_email );
} else {
update_post_meta( $new_coupon_id, 'discount_type', $_discount_type );
update_post_meta( $new_coupon_id, 'coupon_amount', $_coupon_amount );
update_post_meta( $new_coupon_id, 'individual_use', $individual_use );
update_post_meta( $new_coupon_id, 'minimum_amount', $minimum_amount );
update_post_meta( $new_coupon_id, 'maximum_amount', $maximum_amount );
update_post_meta( $new_coupon_id, 'usage_limit', $usage_limit );
update_post_meta( $new_coupon_id, 'customer_email', array( $customer_email ) );
update_post_meta( $new_coupon_id, 'apply_before_tax', $apply_before_tax );
update_post_meta( $new_coupon_id, 'free_shipping', $_free_shipping );
update_post_meta( $new_coupon_id, 'product_categories', array() );
update_post_meta( $new_coupon_id, 'exclude_product_categories', array() );
update_post_meta( $new_coupon_id, 'sc_disable_email_restriction', $disable_email );
}
if ( $this->is_callable( $new_coupon, 'save' ) ) {
$new_coupon->save();
}
$new_generated_coupon_code = $_coupon_code;
$this->save_shortcode_generated_coupon( $new_generated_coupon_code, $current_user, $coupon );
} else {
$new_generated_coupon_code = $shortcode_generated_coupon;
}
}
} else {
$new_generated_coupon_code = $_coupon_code;
}
$new_coupon_generated = false;
if ( ! empty( $new_generated_coupon_code ) ) {
$coupon = new WC_Coupon( $new_generated_coupon_code );
$new_coupon_generated = true;
}
if ( $new_coupon_generated ) {
if ( $this->is_wc_gte_30() ) {
if ( ! is_object( $coupon ) || ! is_callable( array( $coupon, 'get_id' ) ) ) {
return;
}
$coupon_id = $coupon->get_id();
if ( empty( $coupon_id ) ) {
return;
}
$is_free_shipping = ( $coupon->get_free_shipping() ) ? 'yes' : 'no';
$discount_type = $coupon->get_discount_type();
$expiry_date = $coupon->get_date_expires();
$coupon_code = $coupon->get_code();
} else {
$coupon_id = ( ! empty( $coupon->id ) ) ? $coupon->id : 0;
$is_free_shipping = ( ! empty( $coupon->free_shipping ) ) ? $coupon->free_shipping : '';
$discount_type = ( ! empty( $coupon->discount_type ) ) ? $coupon->discount_type : '';
$expiry_date = ( ! empty( $coupon->expiry_date ) ) ? $coupon->expiry_date : '';
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
}
$coupon_amount = $this->get_amount( $coupon, true );
$coupon_post = get_post( $coupon_id );
$coupon_data = $this->get_coupon_meta_data( $coupon );
$design = get_option( 'wc_sc_setting_coupon_design', 'basic' );
$background_color = get_option( 'wc_sc_setting_coupon_background_color', '#39cccc' );
$foreground_color = get_option( 'wc_sc_setting_coupon_foreground_color', '#30050b' );
$third_color = get_option( 'wc_sc_setting_coupon_third_color', '#39cccc' );
$show_coupon_description = get_option( 'smart_coupons_show_coupon_description', 'no' );
$valid_designs = $this->get_valid_coupon_designs();
if ( ! in_array( $design, $valid_designs, true ) ) {
$design = 'basic';
}
if ( 'yes' === $is_email ) {
$design = ( 'custom-design' !== $design ) ? 'email-coupon' : $design;
}
?>
<style type="text/css"><?php echo esc_html( wp_strip_all_tags( $this->get_coupon_styles( $design, array( 'is_email' => $is_email ) ), true ) ); // phpcs:ignore ?></style>
<?php
if ( ! in_array( $design, array( 'custom-design', 'email-coupon' ), true ) ) {
?>
<style type="text/css">
:root {
--sc-color1: <?php echo esc_html( $background_color ); ?>;
--sc-color2: <?php echo esc_html( $foreground_color ); ?>;
--sc-color3: <?php echo esc_html( $third_color ); ?>;
}
</style>
<?php
}
?>
<?php
$coupon_type = ( ! empty( $coupon_data['coupon_type'] ) ) ? $coupon_data['coupon_type'] : '';
if ( 'yes' === $is_free_shipping ) {
if ( ! empty( $coupon_type ) ) {
$coupon_type .= __( ' & ', 'woocommerce-smart-coupons' );
}
$coupon_type .= __( 'Free Shipping', 'woocommerce-smart-coupons' );
}
if ( $this->is_wc_gte_30() && $expiry_date instanceof WC_DateTime ) {
$expiry_date = ( is_callable( array( $expiry_date, 'getTimestamp' ) ) ) ? $expiry_date->getTimestamp() : null;
} elseif ( ! is_int( $expiry_date ) ) {
$expiry_date = $this->strtotime( $expiry_date );
}
if ( ! empty( $expiry_date ) && is_int( $expiry_date ) ) {
$expiry_time = ( $this->is_callable( $coupon, 'get_meta' ) ) ? (int) $coupon->get_meta( 'wc_sc_expiry_time' ) : (int) get_post_meta( $coupon_id, 'wc_sc_expiry_time', true );
if ( ! empty( $expiry_time ) ) {
$expiry_date += $expiry_time; // Adding expiry time to expiry date.
}
}
$coupon_description = '';
if ( ! empty( $coupon_post->post_excerpt ) && 'yes' === $show_coupon_description ) {
$coupon_description = $coupon_post->post_excerpt;
}
$is_percent = $this->is_percent_coupon( array( 'coupon_object' => $coupon ) );
$args = array(
'coupon_object' => $coupon,
'coupon_amount' => $coupon_amount,
'amount_symbol' => ( true === $is_percent ) ? '%' : get_woocommerce_currency_symbol(),
'discount_type' => wp_strip_all_tags( $coupon_type ),
'coupon_description' => ( ! empty( $coupon_description ) ) ? $coupon_description : wp_strip_all_tags( $this->generate_coupon_description( array( 'coupon_object' => $coupon ) ) ),
'coupon_code' => $new_generated_coupon_code,
'coupon_expiry' => ( ! empty( $expiry_date ) ) ? $this->get_expiration_format( $expiry_date ) : __( 'Never expires', 'woocommerce-smart-coupons' ),
'thumbnail_src' => $this->get_coupon_design_thumbnail_src(
array(
'design' => $design,
'coupon_object' => $coupon,
)
),
'classes' => '',
'template_id' => $design,
'is_percent' => $is_percent,
);
$coupon_target = '';
$wc_url_coupons_active_urls = get_option( 'wc_url_coupons_active_urls' ); // From plugin WooCommerce URL coupons.
if ( ! empty( $wc_url_coupons_active_urls ) ) {
$coupon_target = ( ! empty( $wc_url_coupons_active_urls[ $coupon_id ]['url'] ) ) ? $wc_url_coupons_active_urls[ $coupon_id ]['url'] : '';
}
if ( ! empty( $coupon_target ) ) {
$coupon_target = home_url( '/' . $coupon_target );
} else {
$coupon_target = home_url( '/?sc-page=shop&coupon-code=' . $coupon_code );
}
$coupon_target = apply_filters( 'sc_coupon_url_in_email', $coupon_target, $coupon );
do_action(
'wc_sc_before_shortcode_smart_coupons_html_start',
array(
'source' => $this,
'shortcode_attributes' => $shortcode,
'coupon_object' => $coupon,
)
);
if ( 'yes' === $is_email ) {
echo '<div style="margin: 10px 0;" title="' . esc_html__( 'Click to visit store. This coupon will be applied automatically.', 'woocommerce-smart-coupons' ) . '">';
}
if ( 'yes' === $is_clickable ) {
echo '<a href="' . esc_url( $coupon_target ) . '" style="color: #444;">';
}
echo '<div id="sc-cc"><div class="sc-coupons-list">';
wc_get_template( 'coupon-design/' . $design . '.php', $args, '', plugin_dir_path( WC_SC_PLUGIN_FILE ) . 'templates/' );
echo '</div></div>';
if ( 'yes' === $is_clickable ) {
echo '</a>';
}
if ( 'yes' === $is_email ) {
echo '</div>';
}
return ob_get_clean();
}
/**
* Show available coupons
*
* @param array $atts Shortcode attributes.
* @return HTML code for coupon to be displayed
*/
public function show_available_coupons_shortcode( $atts ) {
if ( is_admin() || wp_doing_ajax() || WC()->is_rest_api_request() ) {
return;
}
$shortcode = shortcode_atts(
array(
'title' => get_option( 'smart_coupon_cart_page_text' ),
'categories' => '', // expecting comma-separated term ids.
),
$atts,
'wc_sc_available_coupons'
);
// To override shortcode attributes use filter 'shortcode_atts_wc_sc_available_coupons'. For more details refer this https://developer.wordpress.org/reference/functions/shortcode_atts/.
$title = $shortcode['title'];
$shortcode['categories'] = ( ! empty( $shortcode['categories'] ) && is_string( $shortcode['categories'] ) ) ? explode( ',', $shortcode['categories'] ) : array();
if ( ! class_exists( 'WC_SC_Display_Coupons' ) ) {
include_once 'class-wc-sc-display-coupons.php';
}
$wc_sc_display_coupons = WC_SC_Display_Coupons::get_instance();
if ( ! is_object( $wc_sc_display_coupons ) || ! is_callable( array( $wc_sc_display_coupons, 'show_available_coupons' ) ) ) {
return '';
}
ob_start();
$wc_sc_display_coupons->show_available_coupons(
$title,
get_the_title(),
array(
'source' => $this,
'shortcode_atts' => $shortcode,
)
);
$output = ob_get_clean();
$stripped_output = wp_strip_all_tags( $output, true );
if ( ( ! empty( $title ) && $stripped_output === $title ) || empty( $stripped_output ) ) {
$no_output_text = apply_filters(
'wc_sc_shortcode_no_coupon_found_text',
$this->sc_get_option( 'wc_sc_shortcode_no_coupon_found_text', '' ),
array(
'source' => $this,
'shortcode_atts' => $shortcode,
)
);
return ( ! empty( $no_output_text ) ) ? '<p id="wc-sc-shortcode-no-coupon-found-text">' . wp_kses_post( $no_output_text ) . '</p>' : '';
}
return $output;
}
/**
* Function to check whether to generate a new coupon through shortcode for current user
* Don't create if it is already generated.
*
* @param WP_User $current_user The user object.
* @param WC_Coupon $coupon The coupon object.
* @return string $code
*/
public function get_shortcode_generated_coupon( $current_user = null, $coupon = null ) {
$max_in_a_session = get_option( '_sc_max_coupon_generate_in_a_session', 1 );
$max_per_coupon_per_user = get_option( '_sc_max_coupon_per_coupon_per_user', 1 );
if ( $this->is_wc_gte_30() ) {
$coupon_code = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
} else {
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
$code = ( ! empty( $coupon_code ) ) ? $coupon_code : '';
if ( ! empty( $current_user->ID ) ) {
$generated_coupons = get_user_meta( $current_user->ID, '_sc_shortcode_generated_coupons', true );
if ( ! empty( $generated_coupons[ $code ] ) && count( $generated_coupons[ $code ] ) >= $max_per_coupon_per_user ) {
return end( $generated_coupons[ $code ] );
}
}
$session_shortcode_coupons = ( is_object( WC()->session ) && is_callable( array( WC()->session, 'get' ) ) ) ? WC()->session->get( '_sc_session_shortcode_generated_coupons' ) : array();
if ( ! empty( $session_shortcode_coupons[ $code ] ) && count( $session_shortcode_coupons[ $code ] ) >= $max_in_a_session ) {
return end( $session_shortcode_coupons[ $code ] );
}
return false;
}
/**
* Function to save shortcode generated coupon details
*
* @param string $new_code The coupon code.
* @param WP_User $current_user The user object.
* @param WC_Coupon $coupon The coupon object.
*/
public function save_shortcode_generated_coupon( $new_code, $current_user, $coupon ) {
if ( $this->is_wc_gte_30() ) {
$coupon_code = ( ! empty( $coupon ) && is_callable( array( $coupon, 'get_code' ) ) ) ? $coupon->get_code() : '';
} else {
$coupon_code = ( ! empty( $coupon->code ) ) ? $coupon->code : '';
}
$code = ( ! empty( $coupon_code ) ) ? $coupon_code : 0;
$session_shortcode_coupons = ( is_object( WC()->session ) && is_callable( array( WC()->session, 'get' ) ) ) ? WC()->session->get( '_sc_session_shortcode_generated_coupons' ) : array();
if ( empty( $session_shortcode_coupons ) || ! is_array( $session_shortcode_coupons ) ) {
$session_shortcode_coupons = array();
}
if ( empty( $session_shortcode_coupons[ $code ] ) ) {
$session_shortcode_coupons[ $code ] = array();
}
if ( ! in_array( $new_code, $session_shortcode_coupons[ $code ], true ) ) {
$session_shortcode_coupons[ $code ][] = $new_code;
if ( is_object( WC()->session ) && is_callable( array( WC()->session, 'set' ) ) ) {
WC()->session->set( '_sc_session_shortcode_generated_coupons', $session_shortcode_coupons );
}
}
if ( ! empty( $current_user->ID ) ) {
$generated_coupons = get_user_meta( $current_user->ID, '_sc_shortcode_generated_coupons', true );
if ( empty( $generated_coupons ) ) {
$generated_coupons = array();
}
if ( empty( $generated_coupons[ $code ] ) ) {
$generated_coupons[ $code ] = array();
}
if ( ! in_array( $new_code, $generated_coupons[ $code ], true ) ) {
$generated_coupons[ $code ][] = $new_code;
update_user_meta( $current_user->ID, '_sc_shortcode_generated_coupons', $generated_coupons );
}
}
}
/**
* Smart coupon button after TinyMCE
*
* @param mixed $mce_settings The editor settings.
*/
public function smart_coupons_after_wp_tiny_mce( $mce_settings ) {
if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { // Show shortcode attribute dialog to only top level users.
return;
}
$this->sc_attributes_dialog();
}
/**
* Smart Coupons dialog content for shortcode
*/
public function sc_attributes_dialog() {
?>
<div style="display:none;">
<form id="sc_coupons_attributes" tabindex="-1" style="background-color: #F5F5F5;">
<?php wp_nonce_field( 'internal_coupon_shortcode', '_ajax_coupon_shortcode_nonce', false ); ?>
<script type="text/javascript">
jQuery(function(){
jQuery('input#search-coupon-field').on('keyup',function() {
jQuery('div#search-results ul').empty();
var searchString = jQuery(this).val().trim();
if ( searchString.length == 0 ) {
jQuery('#default-text').html('<?php echo esc_html__( 'No search term specified.', 'woocommerce-smart-coupons' ); ?>');
return true;
}
if ( searchString.length == 1 ) {
jQuery('#default-text').html('<?php echo esc_html__( 'Enter more than one character to search.', 'woocommerce-smart-coupons' ); ?>');
return true;
}
jQuery.ajax({
url: '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>',
method: 'GET',
afterTypeDelay: 100,
data: {
action : 'smart_coupons_json_search',
security : '<?php echo esc_attr( wp_create_nonce( 'search-coupons' ) ); ?>',
term : searchString
},
dataType: 'json',
success: function( response ) {
if ( response ) {
jQuery('#default-text').html('<?php echo esc_html__( 'Click to select coupon code.', 'woocommerce-smart-coupons' ); ?>');
} else {
jQuery('#default-text').html('<?php echo esc_html__( 'No coupon code found.', 'woocommerce-smart-coupons' ); ?>');
return;
}
jQuery('div#search-results ul').html('');
jQuery.each(response, function (i, val) {
jQuery('div#search-results ul').append('<li class="'+i+'">'+ i +val.substr(val.indexOf('(')-1)+'</li>');
});
}
});
});
jQuery('div#sc_shortcode_cancel a').on('click', function() {
emptyAllFormElement();
jQuery('.ui-dialog-titlebar-close').trigger('click');
});
function emptyAllFormElement() {
jQuery('#search-coupon-field').val('');
jQuery('#default-text').html('<?php echo esc_html__( 'No search term specified.', 'woocommerce-smart-coupons' ); ?>');
jQuery('#search-results ul').empty();
}
jQuery('div#search-results').on('click', 'ul li', function() {
var couponCode = jQuery(this).attr('class');
jQuery('input#search-coupon-field').val(couponCode);
});
jQuery('input#sc_shortcode_submit').on('click', function() {
var couponShortcode = '[smart_coupons';
var couponCode = jQuery('#search-coupon-field').val();
if ( couponCode != undefined && couponCode != '' ) {
couponShortcode += ' coupon_code="'+couponCode.trim()+'"';
}
couponShortcode += ' is_clickable="yes"';
couponShortcode += ']';
tinyMCE.execCommand("mceInsertContent", false, couponShortcode);
emptyAllFormElement();
jQuery('.ui-dialog-titlebar-close').trigger('click');
});
});
</script>
<div id="coupon-selector">
<div id="coupon-option">
<div>
<label><span><?php echo esc_html__( 'Coupon code', 'woocommerce-smart-coupons' ); ?></span><input id="search-coupon-field" type="text" name="search_coupon_code" placeholder="<?php echo esc_attr__( 'Search coupon...', 'woocommerce-smart-coupons' ); ?>"/></label>
</div>
<div id="search-panel">
<div id="search-results">
<div id="default-text"><?php echo esc_html__( 'No search term specified.', 'woocommerce-smart-coupons' ); ?></div>
<ul></ul>
</div>
</div>
</div>
</div>
<div id="sc-cc">
<div class="coupon-preview sc-coupons-list">
<div class="preview-heading">
<?php echo esc_html__( 'Preview', 'woocommerce-smart-coupons' ); ?>
</div>
<?php
$design = get_option( 'wc_sc_setting_coupon_design', 'basic' );
$background_color = get_option( 'wc_sc_setting_coupon_background_color', '#39cccc' );
$foreground_color = get_option( 'wc_sc_setting_coupon_foreground_color', '#30050b' );
$third_color = get_option( 'wc_sc_setting_coupon_third_color', '#39cccc' );
$show_coupon_description = get_option( 'smart_coupons_show_coupon_description', 'no' );
$valid_designs = $this->get_valid_coupon_designs();
if ( ! in_array( $design, $valid_designs, true ) ) {
$design = 'basic';
}
?>
<style type="text/css"><?php echo esc_html( wp_strip_all_tags( $this->get_coupon_styles( $design ), true ) ); // phpcs:ignore ?></style>
<?php
if ( 'custom-design' !== $design ) {
?>
<style type="text/css">
:root {
--sc-color1: <?php echo esc_html( $background_color ); ?>;
--sc-color2: <?php echo esc_html( $foreground_color ); ?>;
--sc-color3: <?php echo esc_html( $third_color ); ?>;
}
</style>
<?php
}
?>
<?php
$args = array(
'coupon_amount' => 'XX',
'amount_symbol' => get_woocommerce_currency_symbol(),
'discount_type' => 'Discount type',
'coupon_description' => 'Description',
'coupon_code' => 'coupon-code',
'coupon_expiry' => 'Expires on xx date',
'thumbnail_src' => '',
'classes' => '',
'template_id' => $design,
'is_percent' => false,
);
wc_get_template( 'coupon-design/' . $design . '.php', $args, '', plugin_dir_path( WC_SC_PLUGIN_FILE ) . 'templates/' );
?>
</div>
</div>
<div class="submitbox">
<div id="sc_shortcode_update">
<input type="button" value="<?php echo esc_attr__( 'Insert Shortcode', 'woocommerce-smart-coupons' ); ?>" class="button-primary" id="sc_shortcode_submit" name="sc_shortcode_submit">
</div>
<div id="sc_shortcode_cancel">
<a class="submitdelete deletion" href="#"><?php echo esc_html__( 'Cancel', 'woocommerce-smart-coupons' ); ?></a>
</div>
</div>
</form>
</div>
<?php
}
/**
* Filter coupon ids.
*
* @param array $coupon_ids The coupon ids to filter.
* @param array $args Additional arguments.
* @return array $coupon_ids
*/
public function filter_coupon_ids( $coupon_ids = array(), $args = array() ) {
if ( ! empty( $args['shortcode_atts']['categories'] ) ) {
$coupon_ids = get_objects_in_term( $args['shortcode_atts']['categories'], 'sc_coupon_category' );
}
return $coupon_ids;
}
}
}
WC_SC_Shortcode::get_instance();

View File

@@ -0,0 +1,623 @@
<?php
/**
* Coupons via URL
*
* @author StoreApps
* @since 3.3.0
* @version 2.2.0
*
* @package woocommerce-smart-coupons/includes/
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'WC_SC_URL_Coupon' ) ) {
/**
* Class for handling coupons applied via URL
*/
class WC_SC_URL_Coupon {
/**
* Variable to hold instance of WC_SC_URL_Coupon
*
* @var $instance
*/
private static $instance = null;
/**
* Variable to hold coupon notices
*
* @var $coupon_notices
*/
private $coupon_notices = array();
/**
* Constructor
*/
private function __construct() {
add_action( 'wp_loaded', array( $this, 'apply_coupon_from_url' ), 19 );
add_action( 'wp_loaded', array( $this, 'apply_coupon_from_session' ), 20 );
add_action( 'wp_loaded', array( $this, 'move_applied_coupon_from_cookies_to_account' ) );
add_action( 'wp_head', array( $this, 'convert_sc_coupon_notices_to_wc_notices' ) );
add_filter( 'the_content', array( $this, 'show_coupon_notices' ) );
}
/**
* Get single instance of WC_SC_URL_Coupon
*
* @return WC_SC_URL_Coupon Singleton object of WC_SC_URL_Coupon
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Apply coupon code if passed in the url.
*/
public function apply_coupon_from_url() {
if ( empty( $_SERVER['QUERY_STRING'] ) ) {
return;
}
parse_str( wp_unslash( $_SERVER['QUERY_STRING'] ), $coupon_args ); // phpcs:ignore
$coupon_args = wc_clean( $coupon_args );
if ( ! is_array( $coupon_args ) || empty( $coupon_args ) ) {
return;
}
if ( empty( $coupon_args['coupon-code'] ) ) {
return;
}
$coupons_data = array();
$coupon_args['coupon-code'] = urldecode( $coupon_args['coupon-code'] );
$coupon_codes = explode( ',', $coupon_args['coupon-code'] );
$coupon_codes = array_filter( $coupon_codes ); // Remove empty coupon codes if any.
$max_url_coupons_limit = apply_filters(
'wc_sc_max_url_coupons_limit',
get_option( 'wc_sc_max_url_coupons_limit', 5 ),
array(
'source' => $this,
'query_args' => $coupon_args,
)
);
if ( is_array( $coupon_codes ) ) {
foreach ( $coupon_codes as $coupon_index => $coupon_code ) {
// Process only first five coupons to avoid GET request parameter limit.
if ( $max_url_coupons_limit === $coupon_index ) {
break;
}
if ( empty( $coupon_code ) ) {
continue;
}
$coupons_data[] = array(
'coupon-code' => $coupon_code,
);
}
}
$cart = ( is_object( WC() ) && isset( WC()->cart ) ) ? WC()->cart : null;
$is_cart_empty = is_a( $cart, 'WC_Cart' ) && is_callable( array( $cart, 'is_empty' ) ) && $cart->is_empty();
if ( true === $is_cart_empty ) {
$is_hold = apply_filters(
'wc_sc_hold_applied_coupons',
true,
array(
'coupons_data' => $coupons_data,
'source' => $this,
)
);
if ( true === $is_hold ) {
$this->hold_applied_coupon( $coupons_data );
}
// Set a session cookie to persist the coupon in case the cart is empty. This code will persist the coupon even if the param sc-page is not supplied.
WC()->session->set_customer_session_cookie( true ); // Thanks to: Devon Godfrey.
} else {
foreach ( $coupons_data as $coupon_data ) {
$coupon_code = $coupon_data['coupon-code'];
$coupon = new WC_Coupon( $coupon_code );
if ( ! WC()->cart->has_discount( $coupon_code ) && $this->is_valid( $coupon ) ) {
WC()->cart->add_discount( trim( $coupon_code ) );
}
}
}
if ( ! empty( $coupon_args['add-to-cart'] ) ) {
add_filter( 'woocommerce_add_to_cart_redirect', array( $this, 'add_to_cart_redirect' ), 20, 2 );
return; // Redirection handed over to WooCommerce.
}
if ( empty( $coupon_args['sc-page'] ) ) {
return;
}
$redirect_url = $this->get_sc_redirect_url( $coupon_args );
wp_safe_redirect( $redirect_url );
exit;
}
/**
* Get Smart Coupons redirect url.
*
* @param array $coupon_args Coupon args.
* @return string
*/
public function get_sc_redirect_url( $coupon_args = array() ) {
$redirect_url = '';
if ( empty( $coupon_args ) || ! is_array( $coupon_args ) ) {
return $redirect_url;
}
if ( in_array( $coupon_args['sc-page'], array( 'shop', 'cart', 'checkout', 'myaccount' ), true ) ) {
$page_id = $this->is_wc_gte_30() ? wc_get_page_id( $coupon_args['sc-page'] ) : woocommerce_get_page_id( $coupon_args['sc-page'] );
$redirect_url = get_permalink( $page_id );
} elseif ( is_string( $coupon_args['sc-page'] ) ) {
if ( is_numeric( $coupon_args['sc-page'] ) && ! is_float( $coupon_args['sc-page'] ) ) {
$page = $coupon_args['sc-page'];
} else {
$page = ( function_exists( 'wpcom_vip_get_page_by_path' ) ) ? wpcom_vip_get_page_by_path( $coupon_args['sc-page'], OBJECT, get_post_types() ) : get_page_by_path( $coupon_args['sc-page'], OBJECT, get_post_types() ); // phpcs:ignore
}
$redirect_url = get_permalink( $page );
} elseif ( is_numeric( $coupon_args['sc-page'] ) && ! is_float( $coupon_args['sc-page'] ) ) {
$redirect_url = get_permalink( $coupon_args['sc-page'] );
}
if ( empty( $redirect_url ) ) {
$redirect_url = home_url();
}
// unset known values in the array to re-build URL params below.
if ( isset( $coupon_args['coupon-code'] ) ) {
unset( $coupon_args['coupon-code'] );
}
if ( isset( $coupon_args['sc-page'] ) ) {
unset( $coupon_args['sc-page'] );
}
if ( isset( $coupon_args['add-to-cart'] ) ) {
unset( $coupon_args['add-to-cart'] );
}
// Not using WP's build_query due to performance.
$additional_url_params = http_build_query( $coupon_args );
if ( ! empty( $additional_url_params ) ) {
$redirect_url .= ( ( false === strpos( $additional_url_params, '?' ) ) ? '?' : '&' ) . $additional_url_params;
}
return $this->get_redirect_url_after_smart_coupons_process( $redirect_url );
}
/**
* WooCommerce handles add to cart redirect.
*
* @param string $url The redirect URL.
* @param WC_Product $product Product.
* @return string
*/
public function add_to_cart_redirect( $url = '', $product = null ) {
remove_filter( 'woocommerce_add_to_cart_redirect', array( $this, 'add_to_cart_redirect' ), 20 );
if ( empty( $_SERVER['QUERY_STRING'] ) ) {
return $url;
}
parse_str( wp_unslash( $_SERVER['QUERY_STRING'] ), $coupon_args ); // phpcs:ignore
$coupon_args = wc_clean( $coupon_args );
$cart = ( is_object( WC() ) && isset( WC()->cart ) ) ? WC()->cart : null;
$is_cart_empty = is_a( $cart, 'WC_Cart' ) && is_callable( array( $cart, 'is_empty' ) ) && $cart->is_empty();
if ( false === $is_cart_empty && ! empty( $coupon_args['coupon-code'] ) ) {
$coupon_args['coupon-code'] = urldecode( $coupon_args['coupon-code'] );
$coupon_codes = explode( ',', $coupon_args['coupon-code'] );
$coupon_codes = array_filter( $coupon_codes ); // Remove empty coupon codes if any.
if ( ! empty( $coupon_codes ) ) {
$max_url_coupons_limit = apply_filters( 'wc_sc_max_url_coupons_limit', 5 );
$coupon_codes = ( ! empty( $max_url_coupons_limit ) ) ? array_slice( $coupon_codes, 0, $max_url_coupons_limit ) : array();
foreach ( $coupon_codes as $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code );
if ( ! WC()->cart->has_discount( $coupon_code ) && $this->is_valid( $coupon ) ) {
WC()->cart->add_discount( trim( $coupon_code ) );
}
}
}
}
if ( ! empty( $coupon_args['sc-page'] ) ) {
return $this->get_sc_redirect_url( $coupon_args );
}
return $url;
}
/**
* Apply coupon code from session, if any.
*/
public function apply_coupon_from_session() {
$cart = ( is_object( WC() ) && isset( WC()->cart ) ) ? WC()->cart : null;
if ( empty( $cart ) || WC()->cart->is_empty() ) {
return;
}
$user_id = get_current_user_id();
if ( 0 === $user_id ) {
$unique_id = ( ! empty( $_COOKIE['sc_applied_coupon_profile_id'] ) ) ? wc_clean( wp_unslash( $_COOKIE['sc_applied_coupon_profile_id'] ) ) : ''; // phpcs:ignore
$applied_coupon_from_url = ( ! empty( $unique_id ) ) ? $this->get_applied_coupons_by_guest_user( $unique_id ) : array();
} else {
$applied_coupon_from_url = get_user_meta( $user_id, 'sc_applied_coupon_from_url', true );
}
if ( empty( $applied_coupon_from_url ) || ! is_array( $applied_coupon_from_url ) ) {
return;
}
foreach ( $applied_coupon_from_url as $index => $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code );
if ( $this->is_valid( $coupon ) && ! WC()->cart->has_discount( $coupon_code ) ) {
WC()->cart->add_discount( trim( $coupon_code ) );
unset( $applied_coupon_from_url[ $index ] );
}
}
if ( 0 === $user_id ) {
$this->set_applied_coupon_for_guest_user( $unique_id, $applied_coupon_from_url );
} else {
update_user_meta( $user_id, 'sc_applied_coupon_from_url', $applied_coupon_from_url );
}
}
/**
* Apply coupon code from session, if any.
*
* @param array $coupons_args The coupon arguments.
*/
public function hold_applied_coupon( $coupons_args = array() ) {
if ( empty( $coupons_args ) ) {
return;
}
$user_id = get_current_user_id();
$saved_status = array();
$saved_status = ( 0 === $user_id ) ? $this->save_applied_coupon_in_cookie( $coupons_args ) : $this->save_applied_coupon_in_account( $coupons_args, $user_id );
if ( empty( $saved_status ) ) {
return;
}
foreach ( $coupons_args as $coupon_args ) {
$coupon_code = $coupon_args['coupon-code'];
$save_status = isset( $saved_status[ $coupon_code ] ) ? $saved_status[ $coupon_code ] : '';
if ( 'saved' === $save_status ) {
/* translators: %s: $coupon_code coupon code */
$notice = sprintf( _x( 'Coupon code "%s" applied successfully. Please add some products to the cart to see the discount.', 'This notice will be shown on the cart or the checkout page if the coupon will be applied successfully.', 'woocommerce-smart-coupons' ), $coupon_code );
wc_add_notice( $notice, 'success' );
} elseif ( 'already_saved' === $save_status ) {
/* translators: %s: $coupon_code coupon code */
$notice = sprintf( _x( 'Coupon code "%s" already applied! Please add some products to the cart to see the discount.', 'This notice will be shown on the cart or the checkout page if the coupon is already applied.', 'woocommerce-smart-coupons' ), $coupon_code );
wc_add_notice( $notice, 'error' );
}
}
}
/**
* Apply coupon code from session, if any.
*
* @param array $coupons_args The coupon arguments.
* @return array $saved_status
*/
public function save_applied_coupon_in_cookie( $coupons_args = array() ) {
// Variable to store whether coupons saved/already saved in cookie.
$saved_status = array();
if ( empty( $coupons_args ) ) {
return $saved_status;
}
if ( empty( $_COOKIE['sc_applied_coupon_profile_id'] ) ) {
$unique_id = $this->generate_unique_id();
} else {
$unique_id = wc_clean( wp_unslash( $_COOKIE['sc_applied_coupon_profile_id'] ) ); // phpcs:ignore
}
$applied_coupons = $this->get_applied_coupons_by_guest_user( $unique_id );
foreach ( $coupons_args as $coupon_args ) {
$coupon_code = isset( $coupon_args['coupon-code'] ) ? $coupon_args['coupon-code'] : '';
if ( is_array( $applied_coupons ) && in_array( $coupon_code, $applied_coupons, true ) ) {
$saved_status[ $coupon_code ] = 'already_saved';
} else {
$applied_coupons[] = $coupon_code;
$saved_status[ $coupon_code ] = 'saved';
}
}
$this->set_applied_coupon_for_guest_user( $unique_id, $applied_coupons );
wc_setcookie( 'sc_applied_coupon_profile_id', $unique_id, $this->get_cookie_life() );
return $saved_status;
}
/**
* Apply coupon code from session, if any.
*
* @param array $coupons_args The coupon arguments.
* @param int $user_id The user id.
* @return array $saved_status
*/
public function save_applied_coupon_in_account( $coupons_args = array(), $user_id = 0 ) {
// Variable to store whether coupons saved/already saved in user meta.
$saved_status = array();
if ( ! empty( $coupons_args ) ) {
$applied_coupons = get_user_meta( $user_id, 'sc_applied_coupon_from_url', true );
if ( empty( $applied_coupons ) ) {
$applied_coupons = array();
}
foreach ( $coupons_args as $coupon_args ) {
$coupon_code = $coupon_args['coupon-code'];
if ( ! in_array( $coupon_code, $applied_coupons, true ) ) {
$applied_coupons[] = $coupon_args['coupon-code'];
$saved_status[ $coupon_code ] = 'saved';
} else {
$saved_status[ $coupon_code ] = 'already_saved';
}
}
update_user_meta( $user_id, 'sc_applied_coupon_from_url', $applied_coupons );
}
return $saved_status;
}
/**
* Apply coupon code from session, if any
*/
public function move_applied_coupon_from_cookies_to_account() {
$user_id = get_current_user_id();
if ( $user_id > 0 && ! empty( $_COOKIE['sc_applied_coupon_profile_id'] ) ) {
$unique_id = wc_clean( wp_unslash( $_COOKIE['sc_applied_coupon_profile_id'] ) ); // phpcs:ignore
$applied_coupons = $this->get_applied_coupons_by_guest_user( $unique_id );
if ( false !== $applied_coupons && is_array( $applied_coupons ) && ! empty( $applied_coupons ) ) {
$saved_coupons = get_user_meta( $user_id, 'sc_applied_coupon_from_url', true );
if ( empty( $saved_coupons ) || ! is_array( $saved_coupons ) ) {
$saved_coupons = array();
}
$saved_coupons = array_merge( $saved_coupons, $applied_coupons );
update_user_meta( $user_id, 'sc_applied_coupon_from_url', $saved_coupons );
wc_setcookie( 'sc_applied_coupon_profile_id', '' );
$this->delete_applied_coupons_of_guest_user( $unique_id );
delete_option( 'sc_applied_coupon_profile_' . $unique_id );
}
}
}
/**
* Function to get redirect URL after processing Smart Coupons params
*
* @param string $url The URL.
* @return string $url
*/
public function get_redirect_url_after_smart_coupons_process( $url = '' ) {
if ( empty( $url ) ) {
return $url;
}
$query_string = ( ! empty( $_SERVER['QUERY_STRING'] ) ) ? wc_clean( wp_unslash( $_SERVER['QUERY_STRING'] ) ) : array(); // phpcs:ignore
parse_str( $query_string, $url_args );
$sc_params = array( 'coupon-code', 'sc-page' );
$url_params = array_diff_key( $url_args, array_flip( $sc_params ) );
if ( empty( $url_params['add-to-cart'] ) ) {
$redirect_url = apply_filters( 'wc_sc_redirect_url_after_smart_coupons_process', add_query_arg( $url_params, $url ), array( 'source' => $this ) );
} else {
$redirect_url = apply_filters( 'wc_sc_redirect_url_after_smart_coupons_process', $url, array( 'source' => $this ) );
}
return $redirect_url;
}
/**
* Function to convert sc coupon notices to wc notices
*/
public function convert_sc_coupon_notices_to_wc_notices() {
$coupon_notices = $this->get_coupon_notices();
// If we have coupon notices to be shown and we are on a woocommerce page then convert them to wc notices.
if ( count( $coupon_notices ) > 0 && ( is_woocommerce() || is_cart() || is_checkout() || is_account_page() ) ) {
foreach ( $coupon_notices as $notice_type => $notices ) {
if ( count( $notices ) > 0 ) {
foreach ( $notices as $notice ) {
wc_add_notice( $notice, $notice_type );
}
}
}
$this->remove_coupon_notices();
}
}
/**
* Function to get sc coupon notices
*/
public function get_coupon_notices() {
return apply_filters( 'wc_sc_coupon_notices', $this->coupon_notices );
}
/**
* Function to remove sc coupon notices
*/
public function remove_coupon_notices() {
$this->coupon_notices = array();
}
/**
* Function to add coupon notices to wp content
*
* @param string $content page content.
* @return string $content page content
*/
public function show_coupon_notices( $content = '' ) {
$coupon_notices = $this->get_coupon_notices();
if ( count( $coupon_notices ) > 0 ) {
// Buffer output.
ob_start();
foreach ( $coupon_notices as $notice_type => $notices ) {
if ( count( $coupon_notices[ $notice_type ] ) > 0 ) {
wc_get_template(
"notices/{$notice_type}.php",
array(
'messages' => $coupon_notices[ $notice_type ],
)
);
}
}
$notices = wc_kses_notice( ob_get_clean() );
$content = $notices . $content;
$this->remove_coupon_notices(); // Empty out notice data.
}
return $content;
}
/**
* Function to get coupon codes by guest user's unique ID.
*
* @param string $unique_id Unique ID for guest user.
*
* @return array.
*/
public function get_applied_coupons_by_guest_user( $unique_id = '' ) {
$key = sprintf( 'sc_applied_coupon_profile_%s', $unique_id );
// Get coupons from `transient`.
$coupons = get_transient( $key );
if ( ! empty( $coupons ) && is_array( $coupons ) ) {
return $coupons;
}
// Get coupon from `wp_option`.
return get_option( $key, array() );
}
/**
* Function to set applied coupons for guest user.
*
* @param string $unique_id Unique id for guest user.
* @param array $coupons Array of coupon codes.
*
* @return bool.
*/
public function set_applied_coupon_for_guest_user( $unique_id = '', $coupons = array() ) {
if ( ! empty( $unique_id ) && is_array( $coupons ) ) {
$key = sprintf( 'sc_applied_coupon_profile_%s', $unique_id );
if ( empty( $coupons ) ) {
return delete_transient( $key );
} else {
return set_transient(
$key,
$coupons,
apply_filters( 'wc_sc_applied_coupon_by_url_expire_time', MONTH_IN_SECONDS )
);
}
}
return false;
}
/**
* Function to delete all applied coupons for a guest user.
*
* @param string $unique_id Unique id for guest user.
*
* @return bool.
*/
public function delete_applied_coupons_of_guest_user( $unique_id = '' ) {
if ( ! empty( $unique_id ) ) {
$key = sprintf( 'sc_applied_coupon_profile_%s', $unique_id );
return delete_transient( $key );
}
return false;
}
}
}
WC_SC_URL_Coupon::get_instance();

View File

@@ -0,0 +1,203 @@
<?php
/**
* Compatibility class for WooCommerce 4.4.0
*
* @category Class
* @package WC-compat
* @author StoreApps
* @version 1.1.0
* @since WooCommerce 4.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'SA_WC_Compatibility_4_4' ) ) {
/**
* Class to check WooCommerce version is greater than and equal to 4.4.0
*/
class SA_WC_Compatibility_4_4 {
/**
* Function to check if WooCommerce is Greater Than And Equal To 4.4.0
*
* @return boolean
*/
public static function is_wc_gte_44() {
return self::is_wc_greater_than( '4.3.3' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 4.3.0
*
* @return boolean
*/
public static function is_wc_gte_43() {
return self::is_wc_greater_than( '4.2.2' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 4.2.0
*
* @return boolean
*/
public static function is_wc_gte_42() {
return self::is_wc_greater_than( '4.1.1' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 4.1.0
*
* @return boolean
*/
public static function is_wc_gte_41() {
return self::is_wc_greater_than( '4.0.1' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 4.0.0
*
* @return boolean
*/
public static function is_wc_gte_40() {
return self::is_wc_greater_than( '3.9.3' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.9.0
*
* @return boolean
*/
public static function is_wc_gte_39() {
return self::is_wc_greater_than( '3.8.1' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.8.0
*
* @return boolean
*/
public static function is_wc_gte_38() {
return self::is_wc_greater_than( '3.7.1' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.7.0
*
* @return boolean
*/
public static function is_wc_gte_37() {
return self::is_wc_greater_than( '3.6.5' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.6.0
*
* @return boolean
*/
public static function is_wc_gte_36() {
return self::is_wc_greater_than( '3.5.8' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.5.0
*
* @return boolean
*/
public static function is_wc_gte_35() {
return self::is_wc_greater_than( '3.4.7' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.3.0
*
* @return boolean
*/
public static function is_wc_gte_34() {
return self::is_wc_greater_than( '3.3.5' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.3.0
*
* @return boolean
*/
public static function is_wc_gte_33() {
return self::is_wc_greater_than( '3.2.6' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.2.0
*
* @return boolean
*/
public static function is_wc_gte_32() {
return self::is_wc_greater_than( '3.1.2' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.1.0
*
* @return boolean
*/
public static function is_wc_gte_31() {
return self::is_wc_greater_than( '3.0.9' );
}
/**
* Function to check if WooCommerce is Greater Than And Equal To 3.0.0
*
* @return boolean
*/
public static function is_wc_gte_30() {
return self::is_wc_greater_than( '2.6.14' );
}
/**
* Function to check if WooCommerce version is greater than and equal to 2.6
*
* @return boolean
*/
public static function is_wc_gte_26() {
return self::is_wc_greater_than( '2.5.5' );
}
/**
* Function to check if WooCommerce version is greater than and equal To 2.5
*
* @return boolean
*/
public static function is_wc_gte_25() {
return self::is_wc_greater_than( '2.4.13' );
}
/**
* Function to get WooCommerce version
*
* @return string version or null.
*/
public static function get_wc_version() {
if ( defined( 'WC_VERSION' ) && WC_VERSION ) {
return WC_VERSION;
}
if ( defined( 'WOOCOMMERCE_VERSION' ) && WOOCOMMERCE_VERSION ) {
return WOOCOMMERCE_VERSION;
}
return null;
}
/**
* Function to compare current version of WooCommerce on site with active version of WooCommerce
*
* @param string $version Version number to compare.
* @return bool
*/
public static function is_wc_greater_than( $version ) {
return version_compare( self::get_wc_version(), $version, '>' );
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Compatibility class for WooCommerce 8.7.0
*
* @category Class
* @package WC-compat
* @author StoreApps
* @version 1.1.0
* @since WooCommerce 8.7.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'SA_WC_Compatibility_8_7' ) ) {
/**
* Class to check WooCommerce version is greater than and equal to 8.7.0
*/
class SA_WC_Compatibility_8_7 extends SA_WC_Compatibility_4_4 {
/**
* Function to check if WooCommerce version is greater than and equal To 8.7
*
* @return boolean
*/
public static function is_wc_gte_87() {
return self::is_wc_greater_than( '8.6.1' );
}
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* Compatibility file for WooCommerce Aelia Currency Switcher
*
* @author StoreApps
* @since 6.1.0
* @version 1.0.1
*
* @package woocommerce-smart-coupons/includes/compat/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_Aelia_CS_Compatibility' ) ) {
/**
* Class for handling compatibility with WooCommerce Aelia Currency Switcher
*/
class WC_SC_Aelia_CS_Compatibility {
/**
* Variable to hold instance of WC_SC_Aelia_CS_Compatibility
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
public function __construct() {
add_filter( 'wc_aelia_cs_coupon_types_to_convert', array( $this, 'add_smart_coupon' ) );
}
/**
* Get single instance of WC_SC_Aelia_CS_Compatibility
*
* @return WC_SC_Aelia_CS_Compatibility Singleton object of WC_SC_Aelia_CS_Compatibility
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Add discount type 'smart_coupon' in Aelia Currency Switcher's framework
*
* @param array $coupon_types Existing coupon types.
* @return array $coupon_types
*/
public function add_smart_coupon( $coupon_types = array() ) {
if ( empty( $coupon_types ) || ! is_array( $coupon_types ) ) {
return $coupon_types;
}
if ( ! in_array( 'smart_coupon', $coupon_types, true ) ) {
$coupon_types[] = 'smart_coupon';
}
return $coupon_types;
}
/**
* Check & convert price
*
* @param float $price The price need to be converted.
* @param string $to_currency The price will be converted to this currency.
* @param string $from_currency The price will be converted from this currency.
* @return float
*/
public function convert_price( $price = 0, $to_currency = null, $from_currency = null ) {
if ( empty( $from_currency ) ) {
$from_currency = get_option( 'woocommerce_currency' ); // Shop base currency.
}
if ( empty( $to_currency ) ) {
$to_currency = get_woocommerce_currency(); // Active currency.
}
return apply_filters( 'wc_aelia_cs_convert', $price, $from_currency, $to_currency );
}
}
}
WC_SC_Aelia_CS_Compatibility::get_instance();

View File

@@ -0,0 +1,140 @@
<?php
/**
* Compatibility file for Klarna Checkout for WooCommerce
*
* @author StoreApps
* @since 7.1.0
* @version 1.0.0
*
* @package woocommerce-smart-coupons/includes/compat/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_KCO_Compatibility' ) ) {
/**
* Class for handling compatibility with Klarna Checkout for WooCommerce
*/
class WC_SC_KCO_Compatibility {
/**
* Variable to hold instance of WC_SC_KCO_Compatibility
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
public function __construct() {
add_action( 'wp_loaded', array( $this, 'hooks_for_compatibility' ) );
}
/**
* Add compatibility related functionality
*/
public function hooks_for_compatibility() {
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( is_plugin_active( 'klarna-checkout-for-woocommerce/klarna-checkout-for-woocommerce.php' ) ) {
if ( ! class_exists( 'WC_SC_Purchase_Credit' ) ) {
include_once '../class-wc-sc-purchase-credit.php';
}
if ( class_exists( 'WC_SC_Purchase_Credit' ) ) {
$wc_sc_purchase_credit = WC_SC_Purchase_Credit::get_instance();
$form_position_hook = apply_filters( 'wc_sc_kco_coupon_receiver_detail_form_position_hook', get_option( 'wc_sc_kco_coupon_receiver_detail_form_position_hook', 'kco_wc_before_snippet' ), array( 'source' => $this ) );
add_action( $form_position_hook, array( $wc_sc_purchase_credit, 'gift_certificate_receiver_detail_form' ) );
}
add_action( 'wp_footer', array( $this, 'enqueue_styles_scripts' ), 99 );
}
}
/**
* Get single instance of WC_SC_KCO_Compatibility
*
* @return WC_SC_KCO_Compatibility Singleton object of WC_SC_KCO_Compatibility
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name Function to call.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return mixed Result of function call.
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Enqueue required styles/scripts for store credit frontend form
*/
public function enqueue_styles_scripts() {
// Return if gift certificate form is not shown.
if ( ! did_action( 'wc_sc_gift_certificate_form_shown' ) ) {
return;
}
if ( ! wp_script_is( 'jquery' ) ) {
wp_enqueue_script( 'jquery' );
}
?>
<script type="text/javascript">
jQuery(function(){
if ( typeof wc_sc_ajax_save_coupon_receiver_details_in_session === 'undefined' ) {
function wc_sc_ajax_save_coupon_receiver_details_in_session(){
jQuery.ajax({
url: '<?php echo esc_url( is_callable( array( 'WC_AJAX', 'get_endpoint' ) ) ? WC_AJAX::get_endpoint( 'wc_sc_save_coupon_receiver_details' ) : '/?wc-ajax=wc_sc_save_coupon_receiver_details' ); ?>',
type: 'POST',
dataType: 'json',
data: {
security: '<?php echo esc_html( wp_create_nonce( 'wc-sc-save-coupon-receiver-details' ) ); ?>',
data: jQuery( 'form.checkout' ).serialize()
},
success: function( response ) {
if ( 'yes' !== response.success ) {
console.log('<?php echo esc_html__( 'Failed to update coupon receiver details in session.', 'woocommerce-smart-coupons' ); ?>');
}
}
});
}
}
jQuery('body').on('click', '#klarna-checkout-select-other', wc_sc_ajax_save_coupon_receiver_details_in_session);
});
</script>
<?php
}
}
}
WC_SC_KCO_Compatibility::get_instance();

View File

@@ -0,0 +1,107 @@
<?php
/**
* Compatibility file for WooCommerce Points and Rewards
*
* @author StoreApps
* @since 7.8.0
* @version 1.0.0
*
* @package woocommerce-smart-coupons/includes/compat/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_PNR_Compatibility' ) ) {
/**
* Class for handling compatibility with WooCommerce Points and Rewards
*/
class WC_SC_PNR_Compatibility {
/**
* Variable to hold instance of WC_SC_PNR_Compatibility
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
public function __construct() {
add_action( 'wp_loaded', array( $this, 'hooks_for_compatibility' ) );
}
/**
* Add compatibility related functionality
*/
public function hooks_for_compatibility() {
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( is_plugin_active( 'woocommerce-points-and-rewards/woocommerce-points-and-rewards.php' ) ) {
add_action( 'wc_sc_before_auto_apply_coupons', array( $this, 'before_auto_apply_coupons' ) );
}
}
/**
* Get single instance of WC_SC_PNR_Compatibility
*
* @return WC_SC_PNR_Compatibility Singleton object of WC_SC_PNR_Compatibility
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name Function to call.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return mixed Result of function call.
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Function to execute before auto apply coupons
*
* @param array $args Additional arguments.
*/
public function before_auto_apply_coupons( $args = array() ) {
if ( empty( $args['current_filter'] ) || 'woocommerce_account_content' !== $args['current_filter'] ) {
return;
}
if ( ! has_filter( 'wc_points_rewards_should_render_earn_points_message', '__return_false' ) ) {
add_filter( 'wc_points_rewards_should_render_earn_points_message', '__return_false', 100 );
}
if ( ! has_filter( 'wc_points_rewards_should_render_redeem_points_message', '__return_false' ) ) {
add_filter( 'wc_points_rewards_should_render_redeem_points_message', '__return_false', 100 );
}
}
}
}
WC_SC_PNR_Compatibility::get_instance();

View File

@@ -0,0 +1,88 @@
<?php
/**
* Compatibility file for Woo Multi Currency by VillaTheme https://wordpress.org/plugins/woo-multi-currency/
*
* @author StoreApps
* @since 4.17.0
* @version 1.0.0
*
* @package woocommerce-smart-coupons/includes/compat/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_WMC_Compatibility' ) ) {
/**
* Class for handling compatibility with Woo Multi Currency
*/
class WC_SC_WMC_Compatibility {
/**
* Variable to hold instance of WC_SC_WMC_Compatibility
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
private function __construct() {
add_filter( 'wc_sc_credit_called_price_order', array( $this, 'credit_called_price_order' ), 10, 2 );
add_filter( 'wc_sc_credit_called_price_cart', array( $this, 'credit_called_price_cart' ), 10, 2 );
}
/**
* Get single instance of WC_SC_WMC_Compatibility
*
* @return WC_SC_WMC_Compatibility Singleton object of WC_SC_WMC_Compatibility
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Function to modify the value of the credit called
*
* @param mized $price The price.
* @param array $args Additional arguments.
* @return mized
*/
public function credit_called_price_order( $price = 0, $args = array() ) {
if ( function_exists( 'wmc_get_price' ) ) {
$order = ( ! empty( $args['order_obj'] ) ) ? $args['order_obj'] : null;
$currency = ( is_object( $order ) && is_callable( array( $order, 'get_currency' ) ) ) ? $order->get_currency() : false;
$price = wmc_get_price( $price, $currency );
}
return $price;
}
/**
* Function to modify the value of the credit called
*
* @param mized $price The price.
* @param array $args Additional arguments.
* @return mized
*/
public function credit_called_price_cart( $price = 0, $args = array() ) {
if ( function_exists( 'wmc_get_price' ) ) {
$price = wmc_get_price( $price );
}
return $price;
}
}
}
WC_SC_WMC_Compatibility::get_instance();

View File

@@ -0,0 +1,137 @@
<?php
/**
* Compatibility file for WooPayments Currency
*
* @author StoreApps
* @since 8.18.0
* @version 1.0.0
* @package woocommerce-smart-coupons/includes/compat/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
use WCPay\MultiCurrency\MultiCurrency;
if ( ! class_exists( 'WC_SC_WooPayments_Compatibility' ) ) {
/**
* Class for handling compatibility with WooPayments
*/
class WC_SC_WooPayments_Compatibility {
/**
* Variable to hold instance of WC_SC_WooPayments_Compatibility
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
public function __construct() {
add_filter( 'wcpay_multi_currency_should_convert_product_price', array( $this, 'should_convert_product_price' ), 10, 2 );
}
/**
* Get single instance of WC_SC_WooPayments_Compatibility
*
* @return WC_SC_WooPayments_Compatibility Singleton object of WC_SC_WooPayments_Compatibility
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name Function to call.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return mixed Result of function call.
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Check & convert price
*
* @param float $price The price need to be converted.
* @param string $to_currency The price will be converted to this currency.
* @param string $from_currency The price will be converted from this currency.
* @return float
*/
public function convert_price( $price = 0, $to_currency = null, $from_currency = null ) {
$multicurency = MultiCurrency::instance();
if ( is_callable( array( $multicurency, 'get_raw_conversion' ) ) ) {
if ( ! is_float( $price ) ) {
$price = (float) $price;
}
if ( $from_currency !== $to_currency ) {
$price = $multicurency->get_raw_conversion( $price, $to_currency, $from_currency );
if ( ! empty( $price ) && is_float( $price ) ) {
$price = wc_round_tax_total( $price, 4 );
}
}
}
return $price;
}
/**
* Check if product price should be convert or not
*
* @param bool $should_convert should convert or not.
* @param object $product instance of the product.
* @return float
*/
public function should_convert_product_price( $should_convert = true, $product = null ) {
global $woocommerce_smart_coupon;
if ( ! $product instanceof WC_Product ) {
return $should_convert;
}
$coupons = $woocommerce_smart_coupon->get_coupon_titles( array( 'product_object' => $product ) );
if ( ! empty( $coupons ) && $woocommerce_smart_coupon->is_coupon_amount_pick_from_product_price( $coupons ) ) {
foreach ( $coupons as $coupon_title ) {
$coupon_of_product = new WC_Coupon( $coupon_title );
$discount_type_of_product = ( is_object( $coupon_of_product ) && is_callable( array( $coupon_of_product, 'get_discount_type' ) ) ) ? $coupon_of_product->get_discount_type() : '';
if ( 'smart_coupon' === $discount_type_of_product ) {
return false;
}
}
}
return $should_convert;
}
}
}
WC_SC_WooPayments_Compatibility::get_instance();

View File

@@ -0,0 +1,72 @@
<?php
/**
* Compatibility file for WPML
*
* @author StoreApps
* @since 3.3.0
* @version 1.1.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_WPML_Compatibility' ) ) {
/**
* Class for handling compatibility with WPML
*/
class WC_SC_WPML_Compatibility {
/**
* Variable to hold instance of WC_SC_WPML_Compatibility
*
* @var $instance
*/
private static $instance = null;
/**
* Constructor
*/
public function __construct() {
add_action( 'init', array( $this, 'woocommerce_wpml_compatibility' ), 11 );
}
/**
* Get single instance of WC_SC_WPML_Compatibility
*
* @return WC_SC_WPML_Compatibility Singleton object of WC_SC_WPML_Compatibility
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Function to handle compatibility with WooCommerce Multilingual
*/
public function woocommerce_wpml_compatibility() {
global $woocommerce_wpml;
if ( class_exists( 'woocommerce_wpml' ) && $woocommerce_wpml instanceof woocommerce_wpml ) {
if ( ! empty( $woocommerce_wpml->products ) && has_action( 'woocommerce_before_checkout_process', array( $woocommerce_wpml->products, 'wcml_refresh_cart_total' ) ) ) {
remove_action( 'woocommerce_before_checkout_process', array( $woocommerce_wpml->products, 'wcml_refresh_cart_total' ) );
}
if ( ! empty( $woocommerce_wpml->cart ) && has_action( 'woocommerce_before_checkout_process', array( $woocommerce_wpml->cart, 'wcml_refresh_cart_total' ) ) ) {
remove_action( 'woocommerce_before_checkout_process', array( $woocommerce_wpml->cart, 'wcml_refresh_cart_total' ) );
}
}
}
}
}
WC_SC_WPML_Compatibility::get_instance();

Some files were not shown because too many files have changed in this diff Show More