├── admin ├── assets │ ├── colorpicker │ │ ├── spectrum.css │ │ └── spectrum.js │ ├── css │ │ ├── delete.png │ │ ├── edit.png │ │ ├── help.png │ │ └── thwepo-admin.min.css │ └── js │ │ └── thwepo-admin.min.js ├── class-thwepo-admin-form-field.php ├── class-thwepo-admin-form-section.php ├── class-thwepo-admin-form.php ├── class-thwepo-admin-settings-advanced.php ├── class-thwepo-admin-settings-general.php ├── class-thwepo-admin-settings-license.php ├── class-thwepo-admin-settings.php ├── class-thwepo-admin-utils.php ├── class-thwepo-admin.php └── index.php ├── class-thwepo-license-manager.php ├── includes ├── class-thwepo-activator.php ├── class-thwepo-autoloader.php ├── class-thwepo-data.php ├── class-thwepo-deactivator.php ├── class-thwepo-file.php ├── class-thwepo-i18n.php ├── class-thwepo-loader.php ├── class-thwepo-price.php ├── class-thwepo.php ├── compatibility │ └── class-wepo-wpml-currency-switcher-handler.php ├── index.php ├── model │ ├── class-wepo-section.php │ ├── fields │ │ ├── class-wepo-field-checkbox.php │ │ ├── class-wepo-field-checkboxgroup.php │ │ ├── class-wepo-field-colorpicker.php │ │ ├── class-wepo-field-datepicker.php │ │ ├── class-wepo-field-factory.php │ │ ├── class-wepo-field-file.php │ │ ├── class-wepo-field-heading.php │ │ ├── class-wepo-field-hidden.php │ │ ├── class-wepo-field-html.php │ │ ├── class-wepo-field-inputtext.php │ │ ├── class-wepo-field-label.php │ │ ├── class-wepo-field-multiselect.php │ │ ├── class-wepo-field-number.php │ │ ├── class-wepo-field-password.php │ │ ├── class-wepo-field-radio.php │ │ ├── class-wepo-field-select.php │ │ ├── class-wepo-field-tel.php │ │ ├── class-wepo-field-textarea.php │ │ ├── class-wepo-field-timepicker.php │ │ └── class-wepo-field.php │ └── rules │ │ ├── class-wepo-condition-set.php │ │ ├── class-wepo-condition.php │ │ ├── class-wepo-rule-set.php │ │ └── class-wepo-rule.php └── utils │ ├── class-thwepo-utils-condition.php │ ├── class-thwepo-utils-core.php │ ├── class-thwepo-utils-field.php │ ├── class-thwepo-utils-section.php │ └── class-thwepo-utils.php ├── index.php ├── languages └── woocommerce-extra-product-options-pro.pot ├── public ├── assets │ ├── css │ │ └── thwepo-public.min.css │ └── js │ │ ├── jquery-ui-i18n.min.js │ │ ├── thwepo-public.min.js │ │ └── timepicker │ │ ├── jquery.timepicker.css │ │ └── jquery.timepicker.min.js ├── class-thwepo-public.php └── index.php ├── uninstall.php └── woocommerce-extra-product-options-pro.php /admin/assets/colorpicker/spectrum.css: -------------------------------------------------------------------------------- 1 | /*** 2 | Spectrum Colorpicker v1.8.0 3 | https://github.com/bgrins/spectrum 4 | Author: Brian Grinstead 5 | License: MIT 6 | ***/ 7 | 8 | .sp-container { 9 | position:absolute; 10 | top:0; 11 | left:0; 12 | display:inline-block; 13 | *display: inline; 14 | *zoom: 1; 15 | /* https://github.com/bgrins/spectrum/issues/40 */ 16 | z-index: 9999994; 17 | overflow: hidden; 18 | } 19 | .sp-container.sp-flat { 20 | position: relative; 21 | } 22 | 23 | /* Fix for * { box-sizing: border-box; } */ 24 | .sp-container, 25 | .sp-container * { 26 | -webkit-box-sizing: content-box; 27 | -moz-box-sizing: content-box; 28 | box-sizing: content-box; 29 | } 30 | 31 | /* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */ 32 | .sp-top { 33 | position:relative; 34 | width: 100%; 35 | display:inline-block; 36 | } 37 | .sp-top-inner { 38 | position:absolute; 39 | top:0; 40 | left:0; 41 | bottom:0; 42 | right:0; 43 | } 44 | .sp-color { 45 | position: absolute; 46 | top:0; 47 | left:0; 48 | bottom:0; 49 | right:20%; 50 | } 51 | .sp-hue { 52 | position: absolute; 53 | top:0; 54 | right:0; 55 | bottom:0; 56 | left:84%; 57 | height: 100%; 58 | } 59 | 60 | .sp-clear-enabled .sp-hue { 61 | top:33px; 62 | height: 77.5%; 63 | } 64 | 65 | .sp-fill { 66 | padding-top: 80%; 67 | } 68 | .sp-sat, .sp-val { 69 | position: absolute; 70 | top:0; 71 | left:0; 72 | right:0; 73 | bottom:0; 74 | } 75 | 76 | .sp-alpha-enabled .sp-top { 77 | margin-bottom: 18px; 78 | } 79 | .sp-alpha-enabled .sp-alpha { 80 | display: block; 81 | } 82 | .sp-alpha-handle { 83 | position:absolute; 84 | top:-4px; 85 | bottom: -4px; 86 | width: 6px; 87 | left: 50%; 88 | cursor: pointer; 89 | border: 1px solid black; 90 | background: white; 91 | opacity: .8; 92 | } 93 | .sp-alpha { 94 | display: none; 95 | position: absolute; 96 | bottom: -14px; 97 | right: 0; 98 | left: 0; 99 | height: 8px; 100 | } 101 | .sp-alpha-inner { 102 | border: solid 1px #333; 103 | } 104 | 105 | .sp-clear { 106 | display: none; 107 | } 108 | 109 | .sp-clear.sp-clear-display { 110 | background-position: center; 111 | } 112 | 113 | .sp-clear-enabled .sp-clear { 114 | display: block; 115 | position:absolute; 116 | top:0px; 117 | right:0; 118 | bottom:0; 119 | left:84%; 120 | height: 28px; 121 | } 122 | 123 | /* Don't allow text selection */ 124 | .sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button { 125 | -webkit-user-select:none; 126 | -moz-user-select: -moz-none; 127 | -o-user-select:none; 128 | user-select: none; 129 | } 130 | 131 | .sp-container.sp-input-disabled .sp-input-container { 132 | display: none; 133 | } 134 | .sp-container.sp-buttons-disabled .sp-button-container { 135 | display: none; 136 | } 137 | .sp-container.sp-palette-buttons-disabled .sp-palette-button-container { 138 | display: none; 139 | } 140 | .sp-palette-only .sp-picker-container { 141 | display: none; 142 | } 143 | .sp-palette-disabled .sp-palette-container { 144 | display: none; 145 | } 146 | 147 | .sp-initial-disabled .sp-initial { 148 | display: none; 149 | } 150 | 151 | 152 | /* Gradients for hue, saturation and value instead of images. Not pretty... but it works */ 153 | .sp-sat { 154 | background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0))); 155 | background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0)); 156 | background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); 157 | background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); 158 | background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); 159 | background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0)); 160 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)"; 161 | filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81'); 162 | } 163 | .sp-val { 164 | background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0))); 165 | background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0)); 166 | background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); 167 | background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); 168 | background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); 169 | background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0)); 170 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)"; 171 | filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000'); 172 | } 173 | 174 | .sp-hue { 175 | background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); 176 | background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); 177 | background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); 178 | background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000)); 179 | background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); 180 | background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); 181 | } 182 | 183 | /* IE filters do not support multiple color stops. 184 | Generate 6 divs, line them up, and do two color gradients for each. 185 | Yes, really. 186 | */ 187 | .sp-1 { 188 | height:17%; 189 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00'); 190 | } 191 | .sp-2 { 192 | height:16%; 193 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00'); 194 | } 195 | .sp-3 { 196 | height:17%; 197 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff'); 198 | } 199 | .sp-4 { 200 | height:17%; 201 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff'); 202 | } 203 | .sp-5 { 204 | height:16%; 205 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff'); 206 | } 207 | .sp-6 { 208 | height:17%; 209 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000'); 210 | } 211 | 212 | .sp-hidden { 213 | display: none !important; 214 | } 215 | 216 | /* Clearfix hack */ 217 | .sp-cf:before, .sp-cf:after { content: ""; display: table; } 218 | .sp-cf:after { clear: both; } 219 | .sp-cf { *zoom: 1; } 220 | 221 | /* Mobile devices, make hue slider bigger so it is easier to slide */ 222 | @media (max-device-width: 480px) { 223 | .sp-color { right: 40%; } 224 | .sp-hue { left: 63%; } 225 | .sp-fill { padding-top: 60%; } 226 | } 227 | .sp-dragger { 228 | border-radius: 5px; 229 | height: 5px; 230 | width: 5px; 231 | border: 1px solid #fff; 232 | background: #000; 233 | cursor: pointer; 234 | position:absolute; 235 | top:0; 236 | left: 0; 237 | } 238 | .sp-slider { 239 | position: absolute; 240 | top:0; 241 | cursor:pointer; 242 | height: 3px; 243 | left: -1px; 244 | right: -1px; 245 | border: 1px solid #000; 246 | background: white; 247 | opacity: .8; 248 | } 249 | 250 | /* 251 | Theme authors: 252 | Here are the basic themeable display options (colors, fonts, global widths). 253 | See http://bgrins.github.io/spectrum/themes/ for instructions. 254 | */ 255 | 256 | .sp-container { 257 | border-radius: 0; 258 | background-color: #ECECEC; 259 | border: solid 1px #f0c49B; 260 | padding: 0; 261 | } 262 | .sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear { 263 | font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; 264 | -webkit-box-sizing: border-box; 265 | -moz-box-sizing: border-box; 266 | -ms-box-sizing: border-box; 267 | box-sizing: border-box; 268 | } 269 | .sp-top { 270 | margin-bottom: 3px; 271 | } 272 | .sp-color, .sp-hue, .sp-clear { 273 | border: solid 1px #666; 274 | } 275 | 276 | /* Input */ 277 | .sp-input-container { 278 | float:right; 279 | width: 100px; 280 | margin-bottom: 4px; 281 | } 282 | .sp-initial-disabled .sp-input-container { 283 | width: 100%; 284 | } 285 | .sp-input { 286 | font-size: 12px !important; 287 | border: 1px inset; 288 | padding: 4px 5px; 289 | margin: 0; 290 | width: 100%; 291 | background:transparent; 292 | border-radius: 3px; 293 | color: #222; 294 | } 295 | .sp-input:focus { 296 | border: 1px solid orange; 297 | } 298 | .sp-input.sp-validation-error { 299 | border: 1px solid red; 300 | background: #fdd; 301 | } 302 | .sp-picker-container , .sp-palette-container { 303 | float:left; 304 | position: relative; 305 | padding: 10px; 306 | padding-bottom: 300px; 307 | margin-bottom: -290px; 308 | } 309 | .sp-picker-container { 310 | width: 172px; 311 | border-left: solid 1px #fff; 312 | } 313 | 314 | /* Palettes */ 315 | .sp-palette-container { 316 | border-right: solid 1px #ccc; 317 | } 318 | 319 | .sp-palette-only .sp-palette-container { 320 | border: 0; 321 | } 322 | 323 | .sp-palette .sp-thumb-el { 324 | display: block; 325 | position:relative; 326 | float:left; 327 | width: 24px; 328 | height: 15px; 329 | margin: 3px; 330 | cursor: pointer; 331 | border:solid 2px transparent; 332 | } 333 | .sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active { 334 | border-color: orange; 335 | } 336 | .sp-thumb-el { 337 | position:relative; 338 | } 339 | 340 | /* Initial */ 341 | .sp-initial { 342 | float: left; 343 | border: solid 1px #333; 344 | } 345 | .sp-initial span { 346 | width: 30px; 347 | height: 25px; 348 | border:none; 349 | display:block; 350 | float:left; 351 | margin:0; 352 | } 353 | 354 | .sp-initial .sp-clear-display { 355 | background-position: center; 356 | } 357 | 358 | /* Buttons */ 359 | .sp-palette-button-container, 360 | .sp-button-container { 361 | float: right; 362 | } 363 | 364 | /* Replacer (the little preview div that shows up instead of the ) */ 365 | .sp-replacer { 366 | margin:0; 367 | overflow:hidden; 368 | cursor:pointer; 369 | padding: 4px; 370 | display:inline-block; 371 | *zoom: 1; 372 | *display: inline; 373 | border: solid 1px #91765d; 374 | background: #eee; 375 | color: #333; 376 | vertical-align: middle; 377 | } 378 | .sp-replacer:hover, .sp-replacer.sp-active { 379 | border-color: #F0C49B; 380 | color: #111; 381 | } 382 | .sp-replacer.sp-disabled { 383 | cursor:default; 384 | border-color: silver; 385 | color: silver; 386 | } 387 | .sp-dd { 388 | padding: 2px 0; 389 | height: 16px; 390 | line-height: 16px; 391 | float:left; 392 | font-size:10px; 393 | } 394 | .sp-preview { 395 | position:relative; 396 | width:25px; 397 | height: 20px; 398 | border: solid 1px #222; 399 | margin-right: 5px; 400 | float:left; 401 | z-index: 0; 402 | } 403 | 404 | .sp-palette { 405 | *width: 220px; 406 | max-width: 220px; 407 | } 408 | .sp-palette .sp-thumb-el { 409 | width:16px; 410 | height: 16px; 411 | margin:2px 1px; 412 | border: solid 1px #d0d0d0; 413 | } 414 | 415 | .sp-container { 416 | padding-bottom:0; 417 | } 418 | 419 | 420 | /* Buttons: http://hellohappy.org/css3-buttons/ */ 421 | .sp-container button { 422 | background-color: #eeeeee; 423 | background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc); 424 | background-image: -moz-linear-gradient(top, #eeeeee, #cccccc); 425 | background-image: -ms-linear-gradient(top, #eeeeee, #cccccc); 426 | background-image: -o-linear-gradient(top, #eeeeee, #cccccc); 427 | background-image: linear-gradient(to bottom, #eeeeee, #cccccc); 428 | border: 1px solid #ccc; 429 | border-bottom: 1px solid #bbb; 430 | border-radius: 3px; 431 | color: #333; 432 | font-size: 14px; 433 | line-height: 1; 434 | padding: 5px 4px; 435 | text-align: center; 436 | text-shadow: 0 1px 0 #eee; 437 | vertical-align: middle; 438 | } 439 | .sp-container button:hover { 440 | background-color: #dddddd; 441 | background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb); 442 | background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb); 443 | background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb); 444 | background-image: -o-linear-gradient(top, #dddddd, #bbbbbb); 445 | background-image: linear-gradient(to bottom, #dddddd, #bbbbbb); 446 | border: 1px solid #bbb; 447 | border-bottom: 1px solid #999; 448 | cursor: pointer; 449 | text-shadow: 0 1px 0 #ddd; 450 | } 451 | .sp-container button:active { 452 | border: 1px solid #aaa; 453 | border-bottom: 1px solid #888; 454 | -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; 455 | -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; 456 | -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; 457 | -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; 458 | box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; 459 | } 460 | .sp-cancel { 461 | font-size: 11px; 462 | color: #d93f3f !important; 463 | margin:0; 464 | padding:2px; 465 | margin-right: 5px; 466 | vertical-align: middle; 467 | text-decoration:none; 468 | 469 | } 470 | .sp-cancel:hover { 471 | color: #d93f3f !important; 472 | text-decoration: underline; 473 | } 474 | 475 | 476 | .sp-palette span:hover, .sp-palette span.sp-thumb-active { 477 | border-color: #000; 478 | } 479 | 480 | .sp-preview, .sp-alpha, .sp-thumb-el { 481 | position:relative; 482 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); 483 | } 484 | .sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner { 485 | display:block; 486 | position:absolute; 487 | top:0;left:0;bottom:0;right:0; 488 | } 489 | 490 | .sp-palette .sp-thumb-inner { 491 | background-position: 50% 50%; 492 | background-repeat: no-repeat; 493 | } 494 | 495 | .sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner { 496 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=); 497 | } 498 | 499 | .sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner { 500 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=); 501 | } 502 | 503 | .sp-clear-display { 504 | background-repeat:no-repeat; 505 | background-position: center; 506 | background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==); 507 | } 508 | -------------------------------------------------------------------------------- /admin/assets/css/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pro-WebTech/woocommerce-temp/6a970ed112b66beb0540d3ce2bf7200cb94f67c6/admin/assets/css/delete.png -------------------------------------------------------------------------------- /admin/assets/css/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pro-WebTech/woocommerce-temp/6a970ed112b66beb0540d3ce2bf7200cb94f67c6/admin/assets/css/edit.png -------------------------------------------------------------------------------- /admin/assets/css/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pro-WebTech/woocommerce-temp/6a970ed112b66beb0540d3ce2bf7200cb94f67c6/admin/assets/css/help.png -------------------------------------------------------------------------------- /admin/assets/css/thwepo-admin.min.css: -------------------------------------------------------------------------------- 1 | .align-center{text-align:center!important}.woocommerce-message{margin-top:10px}.err_msgs{color:red}.empty-msg-row{padding:20px 0!important;text-align:center}.status-active{font-size:15px;color:green}.status-deactive{font-size:15px;color:red}.thpladmin-subtitle{font-size:11px;color:#666}.thpladmin-notice a.button-primary{font-size:14px;color:#FFF;background-color:#D9534F;border-color:#D43F3A;line-height:38px;height:40px;padding-left:20px;padding-right:20px}.thpladmin-notice a.button-primary:hover{background-color:#D2322D;border-color:#AC2925}table.thpladmin_fields_table td.sort{cursor:move;font-size:15px;text-align:center}table.thpladmin_fields_table td.sort::before{content:'\f333';font-family:Dashicons;text-align:center;color:#999;display:block;width:17px;float:left;height:100%;line-height:24px}.thpl_logic_label,.thpl_logic_link{cursor:default;display:block;float:left;border:1px solid gray;padding:0 5px;margin-left:5px;margin-right:5px;border-radius:2px}.thpl_logic_link{cursor:pointer;text-decoration:none;color:#FFF!important;background-color:#00A0D2;border:1px solid #0073AA}a.thpl_delete_icon{color:red}a.thpl_delete_icon:hover{opacity:.6;filter:alpha(opacity=60)}.thpladmin-license-settings .info-text,.thpladmin-license-settings-grid{margin-top:30px}.thpladmin-license-settings-grid .dashicons{margin-left:3px;margin-top:8px}.thpladmin-license-settings-grid input[type=text]{padding:5px;width:300px}.thpladmin-license-settings-grid p.submit{margin-top:20px}.thpladmin-license-settings-grid table{margin-top:10px}.thpladmin-license-settings-grid table td,.thpladmin-license-settings-grid table th{padding:5px 0;font-weight:400;vertical-align:middle}.thpladmin-license-settings-grid h2{font-size:14px;margin-bottom:9px;padding-bottom:5px;vertical-align:middle;font-weight:700;border-bottom:1px dashed #cecece}.thpladmin-tab{width:100%;border:0 solid #d4d4d1;border-top:0;background-color:#fff;float:left}.thpladmin-tabs-menu{width:100%;margin:10px 0 0;float:left;clear:both;border-bottom:1px solid #bcd4e6}.thpladmin-tabs-menu li{float:left;margin-right:5px;margin-bottom:-1px;border:1px solid #bcd4e6;outline:transparent solid 1px;border-radius:4px 4px 0 0;background:#e1ecf4}.thpladmin-tabs-menu li.current{color:#555;position:relative;background-color:#fff;border-bottom:1px solid #fff;box-shadow:none}.thpladmin-tabs-menu li.first{margin-left:20px}.thpladmin-tabs-menu li a{font-size:18px;display:block;padding:12px 20px;text-decoration:none;color:#9fc2db;-webkit-transition:color .2s;transition:color .2s}.thpladmin-tabs-menu li a:focus{outline:0;box-shadow:none}.thpladmin-tabs-menu .current a{color:#2e7da3}.thpladmin-tab-content{padding:0;display:none;min-height:200px;max-height:485px;color:#000}.thpladmin-sections{list-style:none;margin:8px 0 0;padding:0;font-size:13px;color:#666}.thpladmin-sections li{display:inline-block;margin:0;padding:0;white-space:nowrap}.thpladmin-sections a.current{font-weight:600;border:none;color:#000}.thpladmin-sections a{line-height:2;padding:.2em;text-decoration:none}.thpladmin-sections .delete_section img,.thpladmin-sections a.edit_section img{width:12px;height:12px}.thpladmin-sections a.add_link{margin-left:30px;background-color:#00A0D2;border:1px solid #0073AA;color:#FFF;padding:2px 5px;border-radius:3px}.thpladmin-sections a.add_link:hover{background-color:#0073AA}.thpladmin-form-table td{padding:5px 0}.thpladmin-form-table td.thpladmin-form-section-title{font-weight:700;border-bottom:1px dashed #cecece}.product_page_th_extra_product_options_pro .ui-dialog{z-index:9990;height:auto!important;padding:0;border-color:#0071a1;border-radius:0}.product_page_th_extra_product_options_pro .ui-widget-overlay{position:fixed}.product_page_th_extra_product_options_pro .ui-dialog td{padding:2px 0}.product_page_th_extra_product_options_pro .ui-dialog .ui-widget-header{color:#fff;background:#004f70;background-image:linear-gradient(#004f70,#005a80)}.product_page_th_extra_product_options_pro .ui-dialog .ui-dialog-titlebar{height:30px;padding:.6em 1em .4em;border:0;border-radius:0}.product_page_th_extra_product_options_pro .ui-dialog .ui-dialog-title{line-height:20px;font-weight:400}.product_page_th_extra_product_options_pro .ui-dialog .ui-dialog-titlebar-close{border:1px solid #fff;background-color:#fff;right:.6em}.product_page_th_extra_product_options_pro .ui-dialog .ui-dialog-titlebar-close:before{display:none}.product_page_th_extra_product_options_pro .ui-dialog .ui-dialog-titlebar-close .ui-icon{background-color:#fff}.product_page_th_extra_product_options_pro .ui-dialog .ui-dialog-buttonpane{border-color:#0071a1}.product_page_th_extra_product_options_pro .ui-dialog .ui-dialog-buttonpane button{color:#0071a1;border-color:#0071a1;background:#f3f5f6;vertical-align:top;height:auto}.product_page_th_extra_product_options_pro .ui-dialog input[type=text],.product_page_th_extra_product_options_pro .ui-dialog select{border-radius:4px;border:1px solid #7e8993;height:34px;padding:0 8px}.product_page_th_extra_product_options_pro .select2-container--default .select2-selection--multiple .select2-selection__rendered{padding:0}.product_page_th_extra_product_options_pro .select2-container--default .select2-selection--multiple .select2-selection__rendered li{font-size:.8em;margin:4px 4px 0 0}.product_page_th_extra_product_options_pro .select2-container--default .select2-selection--multiple .select2-selection__rendered li.select2-search{margin:0;height:26px;width:auto}.thpladmin-popup-wrapper{max-height:400px;overflow-y:scroll}.thpladmin-popup-wrapper input[type=text]:disabled,.thpladmin-popup-wrapper select:disabled{background:#f6f6f6}h1.nav-tab-wrapper,h2.nav-tab-wrapper,h3.nav-tab-wrapper{border-bottom:1px solid #CCC;padding-bottom:0;padding-left:10px}.thpladmin-dynamic-row-table .action-cell{width:30px;text-align:center}.thpladmin-dynamic-row-table .action-cell a.btn{background-color:#00A0D2;border:1px solid #0073AA;color:#FFF;padding:2px 5px;border-radius:3px;font-size:12px;text-decoration:none}.thpladmin-dynamic-row-table .action-cell a.btn-blue{background-color:#00A0D2;border:1px solid #0073AA}.thpladmin-dynamic-row-table .action-cell a.btn-red{background-color:#f66;border:1px solid #ff4c4c}.thpladmin-dynamic-row-table .action-cell a.dashicons{line-height:inherit;font-size:18px;color:#fff;border-radius:3px;box-shadow:0 1px 0 #ccc}.thpladmin-dynamic-row-table .action-cell a.dashicons-plus{background-color:#00A0D2;border:1px solid #0073AA}.thpladmin-dynamic-row-table .action-cell a.dashicons-no-alt{background-color:#f66;border:1px solid #ff4c4c}table.thpladmin-dynamic-row-table td.sort{padding:0;cursor:move;font-size:20px;text-align:center;vertical-align:middle}table.thpladmin-dynamic-row-table td.sort::before{content:'\f333';font-family:Dashicons;text-align:center;line-height:1;color:#999;display:block;width:17px;float:left;height:100%}.thpladmin_fields_table tr.strikeout td{background:rgba(255,0,0,.4)!important;opacity:.6;text-decoration:line-through}.thpladmin_fields_table tr.thpladmin-disabled td{opacity:.4}.thpladmin_fields_table tr.thpladmin-disabled td.td_select{opacity:1}.thpladmin_fields_table .td_actions{width:90px}.thpladmin_fields_table .td_enabled{width:80px}.thpladmin_fields_table .td_clear{width:65px}.thpladmin_fields_table .td_required{width:85px}.thpladmin_fields_table .td_select{width:45px}.thpladmin_fields_table .td_type{width:150px}.thpladmin_fields_table .td_validate{text-transform:capitalize}.thpladmin_fields_table th.status{white-space:nowrap}.thpladmin_fields_table .dashicons{line-height:inherit}.thpladmin_fields_table .td_actions .dashicons{background-color:#f7f7f7;border:1px solid #ccc;border-radius:3px;padding:0 2px 2px;box-shadow:0 1px 0 #ccc;webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.thpladmin_fields_table .td_actions .dashicons.disabled{color:#ccc;border:1px solid #e9e9e9;cursor:default}.thpladmin-sections .dashicons,.thpladmin_fields_table .td_actions .dashicons-admin-page,.thpladmin_fields_table .td_actions .dashicons-edit{cursor:pointer}.thpladmin-sections .dashicons-no{color:#ff4c4c}.iris-picker{z-index:100;display:none;position:absolute!important;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.2)}.iris-picker .ui-slider{border:0!important;margin:0!important;width:auto!important;height:auto!important;background:0 0!important}.iris-picker .ui-slider .ui-slider-handle{margin-bottom:0!important}.thpladmin-colorpickpreview{padding:7px 10px 7px 20px;border:1px solid #7e8993;border-radius:4px 0 0 4px;border-right:1;background-color:#FFF}.product_page_th_extra_product_options_pro .thpladmin-colorpick{border-left:0!important;margin-left:0!important;border-top-left-radius:0!important;border-bottom-left-radius:0!important}.select2-drop-mask{z-index:99999998!important}.select2-container,.select2-drop{z-index:99999999!important}.select2-container .select2-search--inline .select2-search__field{margin-top:0!important;margin-bottom:0!important;border:0!important}.select2-container .select2-search__field{min-width:0!important;background-image:none!important}#thwepo-tab-general_edit,#thwepo-tab-general_new{display:block}#thwepo-tab-general_edit h4,#thwepo-tab-general_new h4,#thwepo-tab-styles_new h4{border-bottom:1px dotted #dededede}.thwepo_tooltip{float:right;display:inline;position:relative;font-size:12px;height:100%;z-index:99999999}.thwepo_tooltip img{padding:0;vertical-align:middle;cursor:help;border:none;height:16px;width:16px}.thwepo_tooltip:hover:after{background:#333;background:rgba(0,0,0,1);border-radius:5px;bottom:26px;color:#fff;content:attr(title);left:-100px;padding:10px 15px;position:absolute;z-index:9998;width:350px}.thwepo_tooltip:hover:before{border:solid;border-color:#000 transparent;border-width:6px 6px 0;bottom:20px;content:"";left:50%;position:absolute;z-index:9999}:root{--primary-bg-color:#007cba;--primary-text-color:#0071a1;--primary-border-color:#0071a1;--primary-alt-bg-color:#f3f5f6;--primary-alt-text-color:#0071a1;--primary-alt-border-color:#0071a1}*{box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}ol,ul{margin-top:0;margin-bottom:10px}:after,:before{box-sizing:border-box}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{cursor:pointer;text-decoration:none;background-color:transparent}.btn-link,a{color:#528ff0}.wp-core-ui select{line-height:2;border-color:#e2e2e2}.pull-right{float:right!important}.ml-30{margin-left:30px!important}.mt-10{margin-top:10px!important}.mt-20{margin-top:20px!important}.p-0{padding:0!important}.ph-5{padding-left:5px!important;padding-right:5px!important}.pv-2{padding-top:2px!important;padding-bottom:2px!important}.thwepo-wrap div.thwepo-notice{margin:10px 20px 0 2px}.thwepo-wrap input[type=text],.thwepo-wrap input[type=number],.thwepo-wrap select,.thwepo-wrap textarea{color:#32373c;line-height:1;min-height:30px;height:36px;width:auto;background-color:#fff;border:1px solid #e2e2e2;border-radius:2px;overflow:hidden;font-size:14px;padding:0 12px;box-shadow:0 0 0 transparent}.thwepo-wrap textarea{height:auto;overflow:auto;padding:2px 6px;line-height:1.5;resize:vertical}.thwepo-wrap input[type=text]:disabled,.thwepo-wrap input[type=number]:disabled,.thwepo-wrap select:disabled,.thwepo-wrap textarea:disabled{color:#a0a5aa;border-color:#ddd;background-color:#f7f7f7}.thwepo-wrap input[type=text]:disabled::placeholder,.thwepo-wrap input[type=number]:disabled::placeholder,.thwepo-wrap select:disabled::placeholder,.thwepo-wrap textarea:disabled::placeholder{color:#a0a5aa}.thwepo-wrap .btn{display:inline-block;background-image:none;font-size:14px;font-weight:400;text-align:center;vertical-align:middle;white-space:nowrap;cursor:pointer;touch-action:manipulation;line-height:1;border-width:1px;border-style:solid;border-radius:2px;outline:0;margin:0;padding:12px 20px;box-sizing:border-box;-webkit-appearance:none;-webkit-box-sizing:border-box;transition:.1s;-webkit-transition:.1s;-ms-user-select:none;-moz-user-select:none;-webkit-user-select:none;color:var(--primary-alt-text-color);background-color:var(--primary-alt-bg-color);border-color:var(--primary-alt-border-color)}.thwepo-wrap .btn:hover{opacity:.9}.thwepo-wrap .btn-small{font-size:13px;padding:8px 10px;border-radius:2px}.thwepo-wrap .btn-tiny{font-size:13px;padding:5px;border-radius:2px}.thwepo-wrap .btn-primary{color:#fff;background-color:var(--primary-bg-color);border-color:var(--primary-border-color)}.thwepo-wrap .btn-primary-alt{color:var(--primary-alt-text-color);background-color:var(--primary-alt-bg-color);border-color:var(--primary-alt-border-color)}.thwepo-wrap .btn-danger{color:#fff;background-color:#f44336;border-color:#c3352b}.thwepo-wrap .btn:disabled,.thwepo-wrap .btn[disabled]{color:#cbcbcb;border-color:#cbcbcb;background-color:#fcfcfc;cursor:default}.thwepo-checkbox{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}.thwepo-checkbox .cb-input,.thwepo-radio .rb-input{display:block;height:0;margin:0;opacity:0;line-height:normal;box-sizing:border-box;overflow:hidden}.thwepo-checkbox .cb-el{width:16px;margin-top:2px;margin-right:8px;height:16px;background:#fff;border-radius:2px;float:left;transition:.3s;cursor:pointer;border:1px solid #ccc}.thwepo-checkbox .cb-el::after{content:'';display:block;width:6px;height:11px;opacity:0;transition:.2s;border:solid #fff;border-width:0 2px 2px 0;transform:rotate(45deg) scale(1.5);margin:0 0 0 4px}.thwepo-checkbox .cb-label{font-size:14px;cursor:pointer;white-space:normal;display:inline-block;font-weight:400;vertical-align:middle}.thwepo-checkbox :checked+.cb-el{background:#528ff0;border-color:#528ff0}.thwepo-checkbox :checked+.cb-el::after{opacity:1;transform:rotate(45deg)}.thwepo-input-wrap{font-weight:400;display:block;margin:24px 0 8px;position:relative}.thwepo-input-wrap .label{float:left;width:172px;text-align:right;margin-bottom:4px;font-weight:700;position:relative}.thwepo-input-wrap.required .label::after{content:'*';font-size:12px;position:absolute;margin-left:1px;top:0;color:#f05050}.thwepo-input-wrap .content{margin-left:190px;position:relative}.thwepo-input-wrap.small .iel-wrapper{width:260px}.thwepo-input-wrap .thwepo-inputtext,.thwepo-input-wrap .thwepo-select{width:100%}.thpladmin-modal-mask{position:fixed;background-color:rgba(17,30,60,.6);top:0;left:0;width:100%;height:100%;z-index:9999;overflow:scroll;transition:opacity 250ms ease-in-out;display:none}.thpladmin-modal .modal-container{position:absolute;background:#fff;border-radius:2px;overflow:hidden;left:50%;top:50%;transform:translate(-50%,-50%);width:90%;max-width:960px;min-height:560px;height:80vh;max-height:640px;animation:appear-down 250ms ease-in-out}.thpladmin-modal .modal-close{position:absolute;color:#58666e;font-size:30px;padding:9px 12px 11px;right:8px;top:8px;line-height:20px;cursor:pointer;z-index:10;user-select:none}.thpladmin-modal .form-wizard{max-width:1024px;height:80vh;max-height:640px;min-height:560px;background:#fafafa;position:relative}.thpladmin-modal .wizard aside{padding:24px 0;width:240px;background:#fff;position:absolute;height:100%;border-right:1px solid #eee}.thpladmin-modal .wizard aside p,.thpladmin-modal .wizard aside side-title{padding:0 24px}.thpladmin-modal .wizard aside side-title{font-size:18px;font-weight:700;display:block;margin-bottom:16px}.thpladmin-modal .form-wizard .sub-title,.thpladmin-modal .form-wizard main-title{text-transform:uppercase;font-weight:600;font-size:14px!important}.thpladmin-modal .wizard aside ul{margin:30px 0;padding:0}.thpladmin-modal .wizard aside li{cursor:pointer;list-style:none;padding:10px 24px;margin:4px 0;color:var(--primary-text-color);position:relative}.thpladmin-modal .wizard aside li.text-primary{color:var(--primary-text-color)}.thpladmin-modal .wizard aside li.active{background:var(--primary-bg-color);color:#fff}.thpladmin-modal .wizard aside li.disabled{display:none}.thpladmin-modal .wizard aside li .dashicons{margin-right:6px;line-height:18px;vertical-align:middle}.thpladmin-modal .wizard aside li.active .dashicons::before{color:#fff}.thpladmin-modal .wizard aside li i.i-chevron-right{font-style:normal;color:#fff;position:absolute;right:8px;font-family:dashicons;opacity:0;top:50%;transform:translate(-4px,-50%);transition:.35s}.thpladmin-modal .wizard aside li.active i.i-chevron-right{opacity:1}.thpladmin-modal .form-wizard main{left:0;right:0;padding:30px;position:absolute;bottom:80px;top:0;overflow:auto}.thpladmin-modal .wizard aside~footer,.thpladmin-modal .wizard aside~main{left:240px}.thpladmin-modal .form-wizard main.main-full{bottom:0}.thpladmin-modal .form-wizard main-title{display:block;margin-bottom:12px}.thpladmin-modal .form-wizard .device-mobile,.thwepo_pp_table tr.disabled.hide{display:none}.thpladmin-modal .form-wizard .device-desktop{display:inline}.thpladmin-modal .form-wizard footer{left:0;padding:10px 20px;right:0;background:#f6f6f6;border-top:1px solid #e0e0e0;bottom:0;position:absolute;text-align:right;z-index:99999999}.thpladmin-modal .form-wizard footer .Loader{float:left;opacity:0;transition:1s opacity;margin-top:4px;line-height:27px}.thpladmin-modal .form-wizard footer .btn-toolbar>.btn{margin-left:5px}.thpladmin-modal .form-wizard .form{margin-top:0;padding-bottom:0}.thpladmin-modal .form-wizard .data-panel-content{margin-top:30px;padding-bottom:90px}.thwepo_pp_table{width:100%}.thwepo_pp_table tr.disabled td.label,.thwepo_pp_table tr.disabled td.tip{opacity:.5}.thwepo_pp_table td{padding:5px 10px}.thwepo_pp_table.compact td{padding:3px 10px}.thwepo_pp_table td.h-separator{padding:20px 0!important}.thwepo_pp_table td.h-separator span{display:block;height:2px;border-top:1px dashed #e6e6e6}.thwepo_pp_table td.label{width:25%;text-align:right;padding-right:0;font-weight:700}.thwepo_pp_table td.tip{width:16px;text-align:center;padding:0}.thwepo_pp_table td.field{padding-left:0}.thwepo_pp_table input[type=text],.thwepo_pp_table input[type=number],.thwepo_pp_table select{width:260px}.thwepo_pp_table input[type=text].thwepo-color{width:223px;border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.thwepo_pp_table .thpladmin-colorpickpreview{padding:9.5px 15px 8.5px 20px;border:1px solid #e2e2e2;border-radius:2px 0 0 2px;border-right:1;background-color:#FFF}.thwepo_pp_table.thwepo-display-rules table{width:100%;padding:0;border-spacing:0;border-collapse:collapse}.thwepo_pp_table.thwepo-display-rules tr{vertical-align:top}.thwepo_pp_table.thwepo-display-rules td{padding:2px 0}.thwepo_pp_table.thwepo-display-rules .rule-action{width:80px}.thwepo-display-rules td.operand-type,.thwepo-display-rules td.operator{width:27%}.thwepo-display-rules td.actions{width:18%;padding-top:10px}.thpl_logic_link{background-color:var(--primary-bg-color);border-color:var(--primary-border-color)}.thwepo-display-rules .ajax-rules td.operand,.thwepo-display-rules .ajax-rules td.operator{width:27%}.thwepo-display-rules .ajax-rules td.value input[type=text],.thwepo-display-rules .ajax-rules td.value select,.thwepo-display-rules td.operand input[type=text],.thwepo-display-rules td.operand select,.thwepo-display-rules td.operand-type input[type=text],.thwepo-display-rules td.operand-type select,.thwepo-display-rules td.operator input[type=text],.thwepo-display-rules td.operator select{width:98%}.product_page_th_extra_product_options_pro .select2-container .select2-selection{border-radius:2px;border:1px solid #e2e2e2;min-height:36px;padding:0 4px}.thpladmin-options-table{width:100%;margin-bottom:30px}.thpladmin-options-table input[type=text],.thpladmin-options-table select{width:100%;padding:0 6px}.thpladmin-options-table td{padding:2px 0 2px 4px}.thpladmin-options-table td.price{width:70px}.thpladmin-options-table td.price-type{width:110px}.thpladmin-options-table td.action-cell{width:100px}.thpladmin-options-table td.action-cell .btn{margin-left:6px;padding:1px 5px 2px;font-size:18px;line-height:1}.thpladmin-options-table td.action-cell span.sort{cursor:move;font-size:18px;padding:0 1px 1px;border-color:#999}.thpladmin-options-table td.action-cell span.sort::before{content:'\f333';content:'\f228';font-family:Dashicons;text-align:center;vertical-align:middle;line-height:1;color:#999}.thwepo-settings-table{width:100%}.thwepo-settings-table td{padding:5px 0}.thwepo-settings-table td.section-title{padding:30px 0 5px;text-align:left;font-weight:700;text-transform:capitalize;border-bottom:1px dashed #cecece}.thwepo-settings-table td.label{width:22%;text-align:left;padding-right:0;font-weight:400}.thwepo-settings-table td.tip{width:16px;text-align:center;padding:0}.thwepo-settings-table td.field{padding-left:0}.thwepo-settings-table textarea{width:90%;font-size:.9em} -------------------------------------------------------------------------------- /admin/class-thwepo-admin-form-section.php: -------------------------------------------------------------------------------- 1 | section_props = $this->get_section_form_props(); 20 | } 21 | 22 | public function get_available_positions(){ 23 | $positions = array( 24 | 'woo_before_add_to_cart_button' => 'Before Add To Cart Button', 25 | 'woo_after_add_to_cart_button' => 'After Add To Cart Button', 26 | 'woo_single_variation_5' => 'Before Variation Price (for variable products)', 27 | /*'woo_before_add_to_cart_quantity' => 'Before Add To Cart Quantity', 28 | 'woo_after_add_to_cart_quantity' => 'After Add To Cart Quantity', 29 | 'woo_before_variations_form' => 'Before Variations Form', 30 | 'woo_after_variations_form' => 'After Variations Form', 31 | 'woo_before_single_variation' => 'Before Single Variation', 32 | 'woo_after_single_variation' => 'After Single Variation', 33 | 'woo_single_variation_90' => 'woo_single_variation_90', 34 | 35 | 'woo_single_product_before_title' => 'Before Title', 36 | 'woo_single_product_after_title' => 'After Title', 37 | 'woo_single_product_before_rating' => 'Before Rating', 38 | 'woo_single_product_after_rating' => 'After Rating', 39 | 'woo_single_product_before_price' => 'Before Price', 40 | 'woo_single_product_after_price' => 'After Price', 41 | 'woo_single_product_before_excerpt' => 'Before Excerpt', 42 | 'woo_single_product_after_excerpt' => 'After Excerpt', 43 | 'woo_single_product_before_add_to_cart' => 'Before Add To Cart', 44 | 'woo_single_product_after_add_to_cart' => 'After Add To Cart', 45 | 'woo_single_product_before_meta' => 'Before Meta', 46 | 'woo_single_product_after_meta' => 'After Meta', 47 | 'woo_single_product_before_sharing' => 'Before Sharing', 48 | 'woo_single_product_after_sharing' => 'After Sharing',*/ 49 | ); 50 | 51 | if(apply_filters('thwepo_enable_additional_positions', false)){ 52 | $positions['woo_before_variations_form'] = 'Before Variations Form'; 53 | } 54 | 55 | return apply_filters('thwepo_extra_fields_display_position', $positions); 56 | } 57 | 58 | public function get_section_form_props(){ 59 | $positions = $this->get_available_positions(); 60 | $html_text_tags = $this->get_html_text_tags(); 61 | 62 | /*$box_types = array( 63 | '' => 'Normal (clear)', 64 | 'box' => 'Box', 65 | 'collapse' => 'Expand and Collapse (start opened)', 66 | 'collapseclosed' => 'Expand and Collapse (start closed)', 67 | 'accordion' => 'Accordion', 68 | );*/ 69 | //$title_positions = array( '' => 'Above field', 'left' => 'Left of the field', 'right' => 'Right of the field', 'disable' => 'Disable' ); 70 | 71 | return array( 72 | 'name' => array('name'=>'name', 'label'=>'Name/ID', 'type'=>'text', 'required'=>1), 73 | 'position' => array('name'=>'position', 'label'=>'Display Position', 'type'=>'select', 'options'=>$positions, 'required'=>1), 74 | //'box_type' => array('name'=>'box_type', 'label'=>'Box Type', 'type'=>'select', 'options'=>$box_types), 75 | 'order' => array('name'=>'order', 'label'=>'Display Order', 'type'=>'text'), 76 | 'cssclass' => array('name'=>'cssclass', 'label'=>'CSS Class', 'type'=>'text'), 77 | 'show_title' => array('name'=>'show_title', 'label'=>'Show section title in product page.', 'type'=>'checkbox', 'value'=>'yes', 'checked'=>1), 78 | 79 | 'title_cell_with' => array('name'=>'title_cell_with', 'label'=>'Col-1 Width', 'type'=>'text', 'value'=>''), 80 | 'field_cell_with' => array('name'=>'field_cell_with', 'label'=>'Col-2 Width', 'type'=>'text', 'value'=>''), 81 | 82 | 'title' => array('name'=>'title', 'label'=>'Title', 'type'=>'text', 'required'=>1), 83 | //'title_position' => array('name'=>'title_position', 'label'=>'Title Position', 'type'=>'select', 'options'=>$title_positions), 84 | 'title_type' => array('name'=>'title_type', 'label'=>'Title Type', 'type'=>'select', 'value'=>'h3', 'options'=>$html_text_tags), 85 | 'title_color' => array('name'=>'title_color', 'label'=>'Title Color', 'type'=>'colorpicker'), 86 | 'title_class' => array('name'=>'title_class', 'label'=>'Title Class', 'type'=>'text'), 87 | 88 | 'subtitle' => array('name'=>'subtitle', 'label'=>'Subtitle', 'type'=>'text'), 89 | //'subtitle_position' => array('name'=>'subtitle_position', 'label'=>'Subtitle Position', 'type'=>'select', 'options'=>$title_positions), 90 | 'subtitle_type' => array('name'=>'subtitle_type', 'label'=>'Subtitle Type', 'type'=>'select', 'value'=>'h3', 'options'=>$html_text_tags), 91 | 'subtitle_color' => array('name'=>'subtitle_color', 'label'=>'Subtitle Color', 'type'=>'colorpicker'), 92 | 'subtitle_class' => array('name'=>'subtitle_class', 'label'=>'Subtitle Class', 'type'=>'text'), 93 | ); 94 | } 95 | 96 | public function output_section_forms(){ 97 | ?> 98 |
99 | output_popup_form_section(); ?> 100 |
101 | 110 |
111 | 178 |
179 | render_form_tab_main_title('Basic Details'); 185 | 186 | ?> 187 |
188 |
189 | 190 | render_form_elm_row($this->section_props['name']); 192 | $this->render_form_elm_row($this->section_props['title']); 193 | $this->render_form_elm_row($this->section_props['subtitle']); 194 | $this->render_form_elm_row($this->section_props['position']); 195 | $this->render_form_elm_row($this->section_props['order']); 196 | $this->render_form_elm_row($this->section_props['title_cell_with']); 197 | $this->render_form_elm_row($this->section_props['field_cell_with']); 198 | 199 | $this->render_form_elm_row_cb($this->section_props['show_title']); 200 | ?> 201 |
202 |
203 | render_form_tab_main_title('Display Settings'); 209 | 210 | ?> 211 |
212 | 213 | render_form_elm_row($this->section_props['cssclass']); 215 | $this->render_form_elm_row($this->section_props['title_class']); 216 | $this->render_form_elm_row($this->section_props['subtitle_class']); 217 | 218 | $this->render_form_elm_row($this->section_props['title_type']); 219 | $this->render_form_elm_row($this->section_props['title_color']); 220 | $this->render_form_elm_row($this->section_props['subtitle_type']); 221 | $this->render_form_elm_row($this->section_props['subtitle_color']); 222 | ?> 223 |
224 |
225 | render_form_tab_main_title('Display Rules'); 231 | 232 | ?> 233 |
234 | 235 | render_form_fragment_rules('section'); 237 | $this->render_form_fragment_rules_ajax('section'); 238 | ?> 239 |
240 |
241 | render_form_tab_main_title('Repeat Rules'); 247 | 248 | ?> 249 |
250 | 252 |
253 | data_prefix = str_ireplace( array( ' ', '_', '&', '?' ), '_', strtolower(THWEPO_SOFTWARE_TITLE) ); 27 | $this->data_prefix = str_ireplace( 'woocommerce', 'th', $this->data_prefix ); 28 | $this->ame_data_key = $this->data_prefix . '_data'; 29 | $this->ame_deactivate_checkbox = $this->data_prefix . '_deactivate_checkbox'; 30 | $this->ame_activation_tab_key = $this->data_prefix . '_license_activate'; 31 | $this->ame_deactivation_tab_key = $this->data_prefix . '_license_deactivate'; 32 | } 33 | 34 | public static function instance() { 35 | if(is_null(self::$_instance)){ 36 | self::$_instance = new self(); 37 | } 38 | return self::$_instance; 39 | } 40 | 41 | public function render_page(){ 42 | settings_errors(); 43 | $this->render_tabs(); 44 | $this->render_content(); 45 | } 46 | 47 | private function render_content(){ 48 | echo do_shortcode('[licensepage_woocommerce_extra_product_options]'); 49 | } 50 | } 51 | 52 | endif; -------------------------------------------------------------------------------- /admin/class-thwepo-admin-settings.php: -------------------------------------------------------------------------------- 1 | page_id = $page; 24 | if($section){ 25 | self::$section_id = $section; 26 | }else{ 27 | self::set_first_section_as_current(); 28 | } 29 | $this->tabs = array( 'general_settings' => 'Product Options', 'advanced_settings' => 'Advanced Settings', 'license_settings' => 'Plugin License'); 30 | } 31 | 32 | public function get_tabs(){ 33 | return $this->tabs; 34 | } 35 | 36 | public function get_current_tab(){ 37 | return $this->page_id; 38 | } 39 | 40 | public function get_sections(){ 41 | return $this->sections; 42 | } 43 | 44 | public function get_current_section(){ 45 | return isset( $_GET['section'] ) ? esc_attr( $_GET['section'] ) : self::$section_id; 46 | } 47 | 48 | public static function set_current_section($section_id){ 49 | if($section_id){ 50 | self::$section_id = $section_id; 51 | } 52 | } 53 | 54 | public static function set_first_section_as_current(){ 55 | $sections = THWEPO_Admin_Utils::get_sections(); 56 | if($sections && is_array($sections)){ 57 | $array_keys = array_keys( $sections ); 58 | if($array_keys && is_array($array_keys) && isset($array_keys[0])){ 59 | self::set_current_section($array_keys[0]); 60 | } 61 | } 62 | } 63 | 64 | public function render_tabs(){ 65 | $current_tab = $this->get_current_tab(); 66 | $tabs = $this->get_tabs(); 67 | 68 | if(empty($tabs)){ 69 | return; 70 | } 71 | 72 | echo ''; 79 | } 80 | 81 | public function render_sections() { 82 | $current_section = $this->get_current_section(); 83 | $sections = $this->get_sections(); 84 | 85 | if(empty($sections)){ 86 | return; 87 | } 88 | 89 | $array_keys = array_keys( $sections ); 90 | $section_html = ''; 91 | 92 | foreach( $sections as $id => $label ){ 93 | $label = THWEPO_i18n::__t($label); 94 | $url = $this->get_admin_url($this->page_id, sanitize_title($id)); 95 | $section_html .= '
  • '.$label.' '.(end($array_keys) == $id ? '' : '|').'
  • '; 96 | } 97 | 98 | if($section_html){ 99 | echo ''; 102 | } 103 | } 104 | 105 | public function get_admin_url($tab = false, $section = false){ 106 | $url = 'edit.php?post_type=product&page=th_extra_product_options_pro'; 107 | if($tab && !empty($tab)){ 108 | $url .= '&tab='. $tab; 109 | } 110 | if($section && !empty($section)){ 111 | $url .= '§ion='. $section; 112 | } 113 | return admin_url($url); 114 | } 115 | 116 | public function print_notices($msg, $type='updated', $return=false){ 117 | $notice = '

    '. THWEPO_i18n::__t($msg) .'

    '; 118 | if(!$return){ 119 | echo $notice; 120 | } 121 | return $notice; 122 | } 123 | 124 | public function render_form_field_element($field, $atts = array(), $render_cell = true){ 125 | if($field && is_array($field)){ 126 | $args = shortcode_atts( array( 127 | 'label_cell_props' => '', 128 | 'input_cell_props' => '', 129 | 'label_cell_colspan' => '', 130 | 'input_cell_colspan' => '', 131 | ), $atts ); 132 | 133 | $ftype = isset($field['type']) ? $field['type'] : 'text'; 134 | $flabel = isset($field['label']) && !empty($field['label']) ? THWEPO_i18n::__t($field['label']) : ''; 135 | $sub_label = isset($field['sub_label']) && !empty($field['sub_label']) ? THWEPO_i18n::__t($field['sub_label']) : ''; 136 | $tooltip = isset($field['hint_text']) && !empty($field['hint_text']) ? THWEPO_i18n::__t($field['hint_text']) : ''; 137 | 138 | $field_html = ''; 139 | 140 | if($ftype == 'text'){ 141 | $field_html = $this->render_form_field_element_inputtext($field, $atts); 142 | 143 | }else if($ftype == 'textarea'){ 144 | $field_html = $this->render_form_field_element_textarea($field, $atts); 145 | 146 | }else if($ftype == 'select'){ 147 | $field_html = $this->render_form_field_element_select($field, $atts); 148 | 149 | }else if($ftype == 'multiselect'){ 150 | $field_html = $this->render_form_field_element_multiselect($field, $atts); 151 | 152 | }else if($ftype == 'colorpicker'){ 153 | $field_html = $this->render_form_field_element_colorpicker($field, $atts); 154 | 155 | }else if($ftype == 'checkbox'){ 156 | $field_html = $this->render_form_field_element_checkbox($field, $atts, $render_cell); 157 | $flabel = ' '; 158 | } 159 | 160 | if($render_cell){ 161 | $required_html = isset($field['required']) && $field['required'] ? '*' : ''; 162 | 163 | $label_cell_props = !empty($args['label_cell_props']) ? $args['label_cell_props'] : ''; 164 | $input_cell_props = !empty($args['input_cell_props']) ? $args['input_cell_props'] : ''; 165 | 166 | ?> 167 | > 168 | 171 |
    172 | 175 | 176 | render_form_fragment_tooltip($tooltip); ?> 177 | > 178 | '', 189 | 'input_name_prefix' => 'i_', 190 | 'input_name_suffix' => '', 191 | ), $atts ); 192 | 193 | $ftype = isset($field['type']) ? $field['type'] : 'text'; 194 | 195 | $input_class = ''; 196 | if($ftype == 'text'){ 197 | $input_class = 'thwepo-inputtext'; 198 | }else if($ftype == 'select'){ 199 | $input_class = 'thwepo-select'; 200 | }else if($ftype == 'multiselect'){ 201 | $input_class = 'thwepo-select thwepo-enhanced-multi-select'; 202 | }else if($ftype == 'colorpicker'){ 203 | $input_class = 'thwepo-color thpladmin-colorpick'; 204 | } 205 | 206 | if($ftype == 'multiselect'){ 207 | $args['input_name_suffix'] = $args['input_name_suffix'].'[]'; 208 | } 209 | 210 | $fname = $args['input_name_prefix'].$field['name'].$args['input_name_suffix']; 211 | $fvalue = isset($field['value']) ? esc_html($field['value']) : ''; 212 | 213 | $input_width = $args['input_width'] ? 'width:'.$args['input_width'].';' : ''; 214 | $field_props = 'name="'. $fname .'" style="'. $input_width .'"'; 215 | $field_props .= !empty($input_class) ? ' class="'. $input_class .'"' : ''; 216 | $field_props .= $ftype == 'textarea' ? '' : ' value="'. $fvalue .'"'; 217 | $field_props .= ( isset($field['placeholder']) && !empty($field['placeholder']) ) ? ' placeholder="'.$field['placeholder'].'"' : ''; 218 | $field_props .= ( isset($field['onchange']) && !empty($field['onchange']) ) ? ' onchange="'.$field['onchange'].'"' : ''; 219 | 220 | return $field_props; 221 | } 222 | 223 | private function render_form_field_element_inputtext($field, $atts = array()){ 224 | $field_html = ''; 225 | if($field && is_array($field)){ 226 | $field_props = $this->prepare_form_field_props($field, $atts); 227 | $field_html = ''; 228 | } 229 | return $field_html; 230 | } 231 | 232 | private function render_form_field_element_textarea($field, $atts = array()){ 233 | $field_html = ''; 234 | if($field && is_array($field)){ 235 | $args = shortcode_atts( array( 236 | 'rows' => '5', 237 | 'cols' => '100', 238 | ), $atts ); 239 | 240 | $fvalue = isset($field['value']) ? $field['value'] : ''; 241 | $field_props = $this->prepare_form_field_props($field, $atts); 242 | $field_html = ''; 243 | } 244 | return $field_html; 245 | } 246 | 247 | private function render_form_field_element_select($field, $atts = array()){ 248 | $field_html = ''; 249 | if($field && is_array($field)){ 250 | $fvalue = isset($field['value']) ? $field['value'] : ''; 251 | $field_props = $this->prepare_form_field_props($field, $atts); 252 | 253 | $field_html = ''; 259 | } 260 | return $field_html; 261 | } 262 | 263 | private function render_form_field_element_multiselect($field, $atts = array()){ 264 | $field_html = ''; 265 | if($field && is_array($field)){ 266 | $field_props = $this->prepare_form_field_props($field, $atts); 267 | 268 | $field_html = ''; 274 | } 275 | return $field_html; 276 | } 277 | 278 | private function render_form_field_element_radio($field, $atts = array()){ 279 | $field_html = ''; 280 | /*if($field && is_array($field)){ 281 | $field_props = $this->prepare_form_field_props($field, $atts); 282 | 283 | $field_html = ''; 289 | }*/ 290 | return $field_html; 291 | } 292 | 293 | private function render_form_field_element_checkbox($field, $atts = array(), $render_cell = true){ 294 | $field_html = ''; 295 | if($field && is_array($field)){ 296 | $args = shortcode_atts( array( 297 | 'label_props' => '', 298 | 'cell_props' => 3, 299 | 'render_input_cell' => false, 300 | ), $atts ); 301 | 302 | $fid = 'a_f'. $field['name']; 303 | $flabel = isset($field['label']) && !empty($field['label']) ? THWEPO_i18n::__t($field['label']) : ''; 304 | 305 | $field_props = $this->prepare_form_field_props($field, $atts); 306 | $field_props .= isset($field['checked']) && $field['checked'] === 1 ? ' checked' : ''; 307 | 308 | $field_html = ''; 309 | $field_html .= ''; 310 | } 311 | if(!$render_cell && $args['render_input_cell']){ 312 | return ''. $field_html .''; 313 | }else{ 314 | return $field_html; 315 | } 316 | } 317 | 318 | private function render_form_field_element_colorpicker($field, $atts = array()){ 319 | $field_html = ''; 320 | if($field && is_array($field)){ 321 | $field_props = $this->prepare_form_field_props($field, $atts); 322 | 323 | $field_html = ''; 324 | $field_html .= ''; 325 | } 326 | return $field_html; 327 | } 328 | 329 | public function render_form_fragment_tooltip($tooltip = false){ 330 | if($tooltip){ 331 | ?> 332 | 333 | 334 | 335 | 338 | 339 | 6, 346 | 'padding-top' => '5px', 347 | 'border-style' => 'dashed', 348 | 'border-width' => '1px', 349 | 'border-color' => '#e6e6e6', 350 | 'content' => '', 351 | ), $atts ); 352 | 353 | $style = $args['padding-top'] ? 'padding-top:'.$args['padding-top'].';' : ''; 354 | $style .= $args['border-style'] ? ' border-bottom:'.$args['border-width'].' '.$args['border-style'].' '.$args['border-color'].';' : ''; 355 | 356 | ?> 357 | 358 |  '; 364 | }*/ 365 | 366 | public function render_field_form_fragment_h_spacing($padding = 5){ 367 | $style = $padding ? 'padding-top:'.$padding.'px;' : ''; 368 | ?> 369 | 370 | 375 |   376 | 381 | 382 | 383 | 384 | get_property('name')] = $section; 26 | return $sections; 27 | } 28 | } 29 | 30 | public static function get_section($section_name){ 31 | if($section_name){ 32 | $sections = self::get_sections(); 33 | if(is_array($sections) && isset($sections[$section_name])){ 34 | $section = $sections[$section_name]; 35 | if(THWEPO_Utils_Section::is_valid_section($section)){ 36 | return $section; 37 | } 38 | } 39 | } 40 | return false; 41 | } 42 | 43 | //Example function to move fields from one section to another. 44 | public static function copy_fields_from_one_to_another($from, $to, $fields){ 45 | if(is_array($fields) && !empty($fields) && $from && $to){ 46 | $sections = THWEPO_Utils::get_custom_sections(); 47 | 48 | if(is_array($sections) && isset($sections[$from]) && isset($sections[$to])){ 49 | $section_from = $sections[$from]; 50 | $section_to = $sections[$to]; 51 | 52 | if(THWEPO_Utils_Section::is_valid_section($section_from) && THWEPO_Utils_Section::is_valid_section($section_to)){ 53 | $update_flag = false; 54 | $field_set_from = THWEPO_Utils_Section::get_fields($section_from); 55 | $field_set_to = THWEPO_Utils_Section::get_fields($section_to); 56 | 57 | foreach($fields as $fname){ 58 | if(!isset($field_set_to[$fname])){ 59 | $field = $field_set_from[$fname]; 60 | $section_to = THWEPO_Utils_Section::add_field($section_to, $field); 61 | $update_flag = true; 62 | } 63 | } 64 | 65 | if($update_flag){ 66 | $sections[$to] = $section_to; 67 | $result = update_option(THWEPO_Utils::OPTION_KEY_CUSTOM_SECTIONS, $sections); 68 | } 69 | } 70 | } 71 | } 72 | } 73 | 74 | public static function skip_products_loading(){ 75 | $skip = apply_filters('thwepo_disable_product_dropdown', false); 76 | return $skip; 77 | } 78 | 79 | public static function load_products($only_id = false){ 80 | $productsList = array(); 81 | $skip = self::skip_products_loading(); 82 | 83 | if(!$skip){ 84 | $limit = apply_filters('thwepo_load_products_per_page', -1); 85 | $only_id = apply_filters('thwepo_load_products_id_only', $only_id); 86 | $status = apply_filters('thwepo_load_products_status', 'publish'); 87 | 88 | $args = array('status' => $status, 'limit' => $limit, 'orderby' => 'name', 'order' => 'ASC', 'return' => 'ids'); 89 | 90 | $products = wc_get_products( $args ); 91 | 92 | if(count($products) > 0){ 93 | if($only_id){ 94 | return $products; 95 | }else{ 96 | foreach($products as $pid){ 97 | //$productsList[] = array("id" => $product->ID, "title" => $product->post_title); 98 | $productsList[] = array("id" => $pid, "title" => get_the_title($pid)); 99 | } 100 | } 101 | } 102 | } 103 | return $productsList; 104 | } 105 | 106 | /*public static function load_products($only_id = false){ 107 | $productsList = array(); 108 | $skip = self::skip_products_loading(); 109 | 110 | if(!$skip){ 111 | $posts_per_page = apply_filters('thwepo_load_products_per_page', -1); 112 | $only_id = apply_filters('thwepo_load_products_id_only', $only_id); 113 | $args = array( 'post_type' => 'product', 'order' => 'ASC', 'posts_per_page' => $posts_per_page, 'fields' => 'ids' ); 114 | 115 | $products = get_posts( $args ); 116 | 117 | if(count($products) > 0){ 118 | if($only_id){ 119 | return $products; 120 | }else{ 121 | foreach($products as $pid){ 122 | //$productsList[] = array("id" => $product->ID, "title" => $product->post_title); 123 | $productsList[] = array("id" => $pid, "title" => get_the_title($pid)); 124 | } 125 | } 126 | } 127 | } 128 | return $productsList; 129 | }*/ 130 | 131 | /*public static function load_products(){ 132 | $args = array( 'post_type' => 'product', 'order' => 'ASC', 'posts_per_page' => -1, 'fields' => 'ids' ); 133 | $products = get_posts( $args ); 134 | $productsList = array(); 135 | 136 | if(count($products) > 0){ 137 | foreach($products as $pid){ 138 | //$productsList[] = array("id" => $product->ID, "title" => $product->post_title); 139 | $productsList[] = array("id" => $pid, "title" => get_the_title($pid)); 140 | } 141 | } 142 | return $productsList; 143 | }*/ 144 | 145 | /*public static function load_products_cat(){ 146 | $ignore_translation = apply_filters('thwepo_ignore_wpml_translation_for_product_category', true); 147 | $is_wpml_active = THWEPO_Utils::is_wpml_active(); 148 | 149 | $product_cat = array(); 150 | $pcat_terms = get_terms('product_cat', 'orderby=count&hide_empty=0'); 151 | 152 | foreach($pcat_terms as $pterm){ 153 | $pcat_slug = $pterm->slug; 154 | $pcat_slug = THWEPO_Utils::check_for_wpml_traslation($pcat_slug, $pterm, $is_wpml_active, $ignore_translation); 155 | 156 | $product_cat[] = array("id" => $pcat_slug, "title" => $pterm->name); 157 | } 158 | return $product_cat; 159 | }*/ 160 | 161 | public static function load_products_cat($only_slug = false){ 162 | $product_cats = self::load_product_terms('category', 'product_cat', $only_slug); 163 | return $product_cats; 164 | } 165 | 166 | public static function load_product_tags($only_slug = false){ 167 | $product_tags = self::load_product_terms('tag', 'product_tag', $only_slug); 168 | return $product_tags; 169 | } 170 | 171 | public static function load_product_terms($type, $taxonomy, $only_slug = false){ 172 | $product_terms = array(); 173 | $pterms = get_terms($taxonomy, 'orderby=count&hide_empty=0'); 174 | 175 | $ignore_translation = true; 176 | $is_wpml_active = THWEPO_Utils::is_wpml_active(); 177 | if($is_wpml_active && $ignore_translation){ 178 | /*global $sitepress; 179 | global $icl_adjust_id_url_filter_off; 180 | $orig_flag_value = $icl_adjust_id_url_filter_off; 181 | $icl_adjust_id_url_filter_off = true; 182 | $default_lang = $sitepress->get_default_language();*/ 183 | $default_lang = THWEPO_Utils::off_wpml_translation(); 184 | } 185 | 186 | if(is_array($pterms)){ 187 | foreach($pterms as $term){ 188 | $dterm = $term; 189 | 190 | if($is_wpml_active && $ignore_translation){ 191 | //$def_term_id = icl_object_id($term->term_id, $type, true, $default_lang); 192 | //$def_term = get_term($def_term_id); 193 | $dterm = THWEPO_Utils::get_default_lang_term($term, $taxonomy, $default_lang); 194 | } 195 | 196 | if($only_slug){ 197 | $product_terms[] = $dterm->slug; 198 | }else{ 199 | $product_terms[] = array("id" => $dterm->slug, "title" => $dterm->name); 200 | } 201 | } 202 | } 203 | 204 | if($is_wpml_active && $ignore_translation){ 205 | //$icl_adjust_id_url_filter_off = $orig_flag_value; 206 | THWEPO_Utils::may_on_wpml_translation($default_lang); 207 | } 208 | 209 | return $product_terms; 210 | } 211 | 212 | public static function load_user_roles(){ 213 | $user_roles = array(); 214 | 215 | global $wp_roles; 216 | $roles = $wp_roles->roles; 217 | //$roles = get_editable_roles(); 218 | foreach($roles as $key => $role){ 219 | $user_roles[] = array("id" => $key, "title" => $role['name']); 220 | } 221 | 222 | return $user_roles; 223 | } 224 | 225 | public static function sort_sections_by_order($a, $b){ 226 | if(is_array($a) && is_array($b)){ 227 | $order_a = isset($a['order']) && is_numeric($a['order']) ? $a['order'] : 0; 228 | $order_b = isset($b['order']) && is_numeric($b['order']) ? $b['order'] : 0; 229 | 230 | if($order_a == $order_b){ 231 | return 0; 232 | } 233 | return ($order_a < $order_b) ? -1 : 1; 234 | }else if(THWEPO_Utils_Section::is_valid_section($a) && THWEPO_Utils_Section::is_valid_section($b)){ 235 | $order_a = is_numeric($a->get_property('order')) ? $a->get_property('order') : 0; 236 | $order_b = is_numeric($b->get_property('order')) ? $b->get_property('order') : 0; 237 | 238 | if($order_a == $order_b){ 239 | return 0; 240 | } 241 | return ($order_a < $order_b) ? -1 : 1; 242 | }else{ 243 | return 0; 244 | } 245 | } 246 | 247 | public static function stable_uasort(&$array, $cmp_function) { 248 | if(count($array) < 2) { 249 | return; 250 | } 251 | 252 | $halfway = count($array) / 2; 253 | $array1 = array_slice($array, 0, $halfway, TRUE); 254 | $array2 = array_slice($array, $halfway, NULL, TRUE); 255 | 256 | self::stable_uasort($array1, $cmp_function); 257 | self::stable_uasort($array2, $cmp_function); 258 | if(call_user_func_array($cmp_function, array(end($array1), reset($array2))) < 1) { 259 | $array = $array1 + $array2; 260 | return; 261 | } 262 | 263 | $array = array(); 264 | reset($array1); 265 | reset($array2); 266 | while(current($array1) && current($array2)) { 267 | if(call_user_func_array($cmp_function, array(current($array1), current($array2))) < 1) { 268 | $array[key($array1)] = current($array1); 269 | next($array1); 270 | } else { 271 | $array[key($array2)] = current($array2); 272 | next($array2); 273 | } 274 | } 275 | while(current($array1)) { 276 | $array[key($array1)] = current($array1); 277 | next($array1); 278 | } 279 | while(current($array2)) { 280 | $array[key($array2)] = current($array2); 281 | next($array2); 282 | } 283 | return; 284 | } 285 | } 286 | 287 | endif; -------------------------------------------------------------------------------- /admin/class-thwepo-admin.php: -------------------------------------------------------------------------------- 1 | plugin_name = $plugin_name; 28 | $this->version = $version; 29 | 30 | //$this->init_product_settings(); 31 | } 32 | 33 | public function enqueue_styles_and_scripts($hook) { 34 | if(strpos($hook, 'product_page_th_extra_product_options_pro') === false) { 35 | return; 36 | } 37 | $debug_mode = apply_filters('thwepo_debug_mode', false); 38 | $suffix = $debug_mode ? '' : '.min'; 39 | 40 | $this->enqueue_styles($suffix); 41 | $this->enqueue_scripts($suffix); 42 | } 43 | 44 | private function enqueue_styles($suffix) { 45 | wp_enqueue_style('jquery-ui-style', '//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css?ver=1.11.4'); 46 | wp_enqueue_style('woocommerce_admin_styles', THWEPO_WOO_ASSETS_URL.'css/admin.css'); 47 | wp_enqueue_style('wp-color-picker'); 48 | wp_enqueue_style('thwepo-admin-style', THWEPO_ASSETS_URL_ADMIN . 'css/thwepo-admin'. $suffix .'.css', $this->version); 49 | //wp_enqueue_style('thwepo-colorpicker-style', THWEPO_ASSETS_URL_ADMIN . 'colorpicker/spectrum.css'); 50 | } 51 | 52 | private function enqueue_scripts($suffix) { 53 | $deps = array('jquery', 'jquery-ui-dialog', 'jquery-ui-sortable', 'jquery-tiptip', 'wc-enhanced-select', 'selectWoo', 'wp-color-picker'); 54 | //$deps = array('jquery', 'jquery-ui-dialog', 'jquery-ui-sortable', 'jquery-tiptip', 'woocommerce_admin', 'wc-enhanced-select', 'selectWoo', 'wp-color-picker'); 55 | 56 | /*wp_enqueue_script('thwepo-admin-base', THWEPO_ASSETS_URL_ADMIN . 'js/inc/thwepo-admin-base.js', $deps, $this->version, false); 57 | wp_enqueue_script('thwepo-admin-conditions', THWEPO_ASSETS_URL_ADMIN . 'js/inc/thwepo-admin-conditions.js', array('thwepo-admin-base'), $this->version, false); 58 | wp_enqueue_script('thwepo-admin-script', THWEPO_ASSETS_URL_ADMIN . 'js/inc/thwepo-admin.js', array('thwepo-admin-base', 'thwepo-admin-conditions'), $this->version, false); 59 | wp_enqueue_script('thwepo-admin-conditions', THWEPO_ASSETS_URL_ADMIN . 'js/inc/thwepo-admin-advanced.js', array('thwepo-admin-base'), $this->version, false); 60 | */ 61 | wp_enqueue_script( 'thwepo-admin-script', THWEPO_ASSETS_URL_ADMIN . 'js/thwepo-admin'. $suffix .'.js', $deps, $this->version, false ); 62 | 63 | $wepo_var = array( 64 | 'admin_url' => admin_url(), 65 | 'ajax_url' => admin_url( 'admin-ajax.php' ), 66 | ); 67 | wp_localize_script('thwepo-admin-script', 'wepo_var', $wepo_var); 68 | } 69 | 70 | public function wepo_capability() { 71 | $allowed = array('manage_woocommerce', 'manage_options'); 72 | $capability = apply_filters('thwepo_required_capability', 'manage_woocommerce'); 73 | 74 | if(!in_array($capability, $allowed)){ 75 | $capability = 'manage_woocommerce'; 76 | } 77 | return $capability; 78 | } 79 | 80 | public function admin_menu() { 81 | $capability = $this->wepo_capability(); 82 | $this->screen_id = add_submenu_page('edit.php?post_type=product', THWEPO_i18n::__t('WooCommerce Extra Product Option'), 83 | THWEPO_i18n::__t('Live Preview'), $capability, 'th_extra_product_options_pro', array($this, 'output_settings')); 84 | 85 | //add_action('admin_print_scripts-'. $this->screen_id, array($this, 'enqueue_admin_scripts')); 86 | } 87 | 88 | public function add_screen_id($ids){ 89 | $ids[] = 'woocommerce_page_th_extra_product_options_pro'; 90 | $ids[] = strtolower( THWEPO_i18n::__t('WooCommerce') ) .'_page_th_extra_product_options_pro'; 91 | 92 | return $ids; 93 | } 94 | 95 | /*public function init_product_settings(){ 96 | $prod_settings = THWEPO_Admin_Settings_Product::instance(); 97 | $prod_settings->render_page(); 98 | }*/ 99 | 100 | public function plugin_action_links($links) { 101 | $settings_link = ''. __('Settings') .''; 102 | array_unshift($links, $settings_link); 103 | return $links; 104 | } 105 | 106 | public function plugin_row_meta( $links, $file ) { 107 | if(THWEPO_BASE_NAME == $file) { 108 | $doc_link = esc_url('https://www.themehigh.com/help-guides/woocommerce-extra-product-options/'); 109 | $support_link = esc_url('https://www.themehigh.com/help-guides/'); 110 | 111 | $row_meta = array( 112 | 'docs' => ''.THWEPO_i18n::esc_html__t('Docs').'', 113 | 'support' => ''. THWEPO_i18n::esc_html__t('Premium support') .'', 114 | ); 115 | 116 | return array_merge( $links, $row_meta ); 117 | } 118 | return (array) $links; 119 | } 120 | 121 | public function output_settings(){ 122 | $tab = isset( $_GET['tab'] ) ? esc_attr( $_GET['tab'] ) : 'general_settings'; 123 | 124 | echo '
    '; 125 | if($tab === 'advanced_settings'){ 126 | $advanced_settings = THWEPO_Admin_Settings_Advanced::instance(); 127 | $advanced_settings->render_page(); 128 | }else if($tab === 'license_settings'){ 129 | $license_settings = THWEPO_Admin_Settings_License::instance(); 130 | $license_settings->render_page(); 131 | }else{ 132 | $general_settings = THWEPO_Admin_Settings_General::instance(); 133 | $general_settings->render_page(); 134 | } 135 | echo ''; 136 | } 137 | } 138 | 139 | endif; -------------------------------------------------------------------------------- /admin/index.php: -------------------------------------------------------------------------------- 1 | = 2.0){ 45 | self::may_copy_free_version_settings_200(); 46 | }else{ 47 | self::may_copy_free_version_settings_134(); 48 | } 49 | } 50 | 51 | /*********************************************** 52 | ****** Copy Setting from version < 2.0.0 ****** 53 | ***********************************************/ 54 | public static function may_copy_free_version_settings_134(){ 55 | $extra_options = get_option('thwepof_custom_product_fields'); 56 | 57 | if($extra_options && is_array($extra_options)){ 58 | $section = THWEPO_Utils_Section::prepare_default_section(); 59 | $section = self::prepare_section_and_fields_134($section, $extra_options); 60 | $section = THWEPO_Utils_Section::sort_fields($section); 61 | 62 | $general_settings = new THWEPO_Admin_Settings_General(); 63 | $result1 = $general_settings->update_section($section); 64 | $result2 = $general_settings->update_options_name_title_map(); 65 | 66 | delete_option('thwepof_custom_product_fields'); 67 | } 68 | } 69 | 70 | public static function prepare_section_and_fields_134($section, $extra_options){ 71 | foreach($extra_options as $hook => $fields){ 72 | if($fields){ 73 | foreach($fields as $field_name => $field){ 74 | try{ 75 | $new_field = self::prepare_fields_134($field); 76 | $section = THWEPO_Utils_Section::add_field($section, $new_field); 77 | } catch (Exception $e) { 78 | } 79 | } 80 | } 81 | } 82 | return $section; 83 | } 84 | 85 | public static function prepare_fields_134($field){ 86 | $new_field = false; 87 | 88 | if($field){ 89 | $type = $field->get_property('type'); 90 | $order = $field->get_property('order'); 91 | $id = $field->get_property('id'); 92 | $name = $field->get_property('name'); 93 | $value = $field->get_property('value'); 94 | $placeholder = $field->get_property('placeholder'); 95 | $validate = $field->get_property('validator'); 96 | $cssclass = $field->get_property('cssclass'); 97 | $title = $field->get_property('title'); 98 | $title_position = $field->get_property('title_position'); 99 | $title_class = $field->get_property('title_class'); 100 | $cols = $field->get_property('cols'); 101 | $rows = $field->get_property('rows'); 102 | $checked = $field->get_property('checked'); 103 | $required = $field->is_required(); 104 | $enabled = $field->is_enabled(); 105 | $conditional_rules = $field->get_property('conditional_rules'); 106 | 107 | $new_field = THWEPO_Utils_Field::create_field($type); 108 | $new_field->set_property('order', $order); 109 | $new_field->set_property('id', $id); 110 | $new_field->set_property('name', $name); 111 | $new_field->set_property('value', $value); 112 | $new_field->set_property('placeholder', $placeholder); 113 | $new_field->set_property('validate', $validate); 114 | $new_field->set_property('cssclass', $cssclass); 115 | $new_field->set_property('title', $title); 116 | $new_field->set_property('title_position', $title_position); 117 | $new_field->set_property('title_type', 'label'); 118 | $new_field->set_property('title_class', $title_class); 119 | $new_field->set_property('cols', $cols); 120 | $new_field->set_property('rows', $rows); 121 | $new_field->set_property('checked', $checked); 122 | $new_field->set_property('required', $required); 123 | $new_field->set_property('enabled', $enabled); 124 | 125 | if($type === 'select' || $type === 'radio'){ 126 | $new_options = array(); 127 | 128 | $options = $field->get_property('options'); 129 | if($options && is_array($options)){ 130 | foreach($options as $option){ 131 | $new_option = array(); 132 | $new_option['key'] = $option; 133 | $new_option['text'] = $option; 134 | $new_option['price'] = ''; 135 | $new_option['price_type'] = ''; 136 | 137 | $new_options[$option] = $new_option; 138 | } 139 | } 140 | 141 | $new_options_json = json_encode($new_options); 142 | $new_options_json = rawurlencode($new_options_json); 143 | $new_options_json = trim(stripslashes($new_options_json)); 144 | 145 | $new_field->set_property('options', $new_options); 146 | $new_field->set_property('options_json', $new_options_json); 147 | } 148 | 149 | $new_field = self::prepare_conditional_rules($new_field, $conditional_rules); 150 | $new_field = THWEPO_Utils_Field::prepare_properties($new_field); 151 | } 152 | return $new_field; 153 | } 154 | 155 | /*********************************************** 156 | ****** Copy Setting from version >= 2.0.0 ***** 157 | ***********************************************/ 158 | public static function may_copy_free_version_settings_200(){ 159 | if(class_exists('THWEPOF_Section') && class_exists('WEPOF_Product_Field')){ 160 | $custom_sections = get_option('thwepof_custom_sections'); 161 | 162 | if(is_array($custom_sections)){ 163 | $advanced_settings = get_option('thwepof_advanced_settings'); 164 | $general_settings = new THWEPO_Admin_Settings_General(); 165 | $result = true; 166 | 167 | foreach($custom_sections as $key => $sectionf){ 168 | $section = self::prepare_section_200($sectionf, $advanced_settings); 169 | if($section){ 170 | $result1 = $general_settings->update_section($section); 171 | $result2 = $general_settings->update_options_name_title_map(); 172 | 173 | if(!$result1 || !$result2){ 174 | $result = false; 175 | } 176 | } 177 | } 178 | 179 | if($result){ 180 | //delete_option('thwepof_custom_sections'); 181 | //delete_option('thwepof_section_hook_map'); 182 | //delete_option('thwepof_options_name_title_map'); 183 | } 184 | } 185 | } 186 | 187 | self::may_copy_advanced_settings(); 188 | } 189 | 190 | public static function prepare_section_200($sectionf, $advanced_settings=array()){ 191 | try{ 192 | if($sectionf instanceof THWEPOF_Section){ 193 | $section = new WEPO_Product_Page_Section(); 194 | $section->set_property('id', $sectionf->get_property('id')); 195 | $section->set_property('name', $sectionf->get_property('name')); 196 | $section->set_property('title', $sectionf->get_property('title')); 197 | $section->set_property('show_title', $sectionf->get_property('show_title')); 198 | $section->set_property('position', $sectionf->get_property('position')); 199 | 200 | $fields = $sectionf->get_property('fields'); 201 | if(is_array($fields)){ 202 | $hide_in_cart = isset($advanced_settings['hide_in_cart']) ? $advanced_settings['hide_in_cart'] : false; 203 | $hide_in_order = isset($advanced_settings['hide_in_order']) ? $advanced_settings['hide_in_order'] : false; 204 | $hide_in_checkout = isset($advanced_settings['hide_in_checkout']) ? $advanced_settings['hide_in_checkout'] : false; 205 | 206 | foreach($fields as $key => $fieldf){ 207 | $field = self::prepare_field_200($fieldf); 208 | if($field){ 209 | $field->set_property('hide_in_cart', $hide_in_cart); 210 | $field->set_property('hide_in_order', $hide_in_order); 211 | $field->set_property('hide_in_checkout', $hide_in_checkout); 212 | 213 | $section = THWEPO_Utils_Section::add_field($section, $field); 214 | } 215 | } 216 | $section = THWEPO_Utils_Section::sort_fields($section); 217 | } 218 | 219 | $conditional_rules = $sectionf->get_property('conditional_rules'); 220 | $section = self::prepare_conditional_rules($section, $conditional_rules); 221 | 222 | return $section; 223 | } 224 | }catch (Exception $e) { 225 | return false; 226 | } 227 | return false; 228 | } 229 | 230 | public static function prepare_field_200($field){ 231 | $new_field = false; 232 | 233 | if($field instanceof WEPOF_Product_Field){ 234 | $type = $field->get_property('type'); 235 | $order = $field->get_property('order'); 236 | $id = $field->get_property('id'); 237 | $name = $field->get_property('name'); 238 | $value = $field->get_property('value'); 239 | $placeholder = $field->get_property('placeholder'); 240 | $validate = $field->get_property('validator'); 241 | $cssclass = $field->get_property('cssclass'); 242 | $title = $field->get_property('title'); 243 | $title_position = $field->get_property('title_position'); 244 | $title_class = $field->get_property('title_class'); 245 | $cols = $field->get_property('cols'); 246 | $rows = $field->get_property('rows'); 247 | $checked = $field->get_property('checked'); 248 | $required = $field->is_required(); 249 | $enabled = $field->is_enabled(); 250 | $readonly = $field->is_readonly(); 251 | $conditional_rules = $field->get_property('conditional_rules'); 252 | 253 | $type = $type === 'paragraph' ? 'label' : $type; 254 | 255 | $new_field = THWEPO_Utils_Field::create_field($type); 256 | $new_field->set_property('order', $order); 257 | $new_field->set_property('id', $id); 258 | $new_field->set_property('name', $name); 259 | $new_field->set_property('value', $value); 260 | $new_field->set_property('placeholder', $placeholder); 261 | $new_field->set_property('validate', $validate); 262 | $new_field->set_property('cssclass', $cssclass); 263 | $new_field->set_property('title', $title); 264 | $new_field->set_property('title_position', $title_position); 265 | $new_field->set_property('title_type', 'label'); 266 | $new_field->set_property('title_class', $title_class); 267 | $new_field->set_property('cols', $cols); 268 | $new_field->set_property('rows', $rows); 269 | $new_field->set_property('checked', $checked); 270 | $new_field->set_property('required', $required); 271 | $new_field->set_property('enabled', $enabled); 272 | $new_field->set_property('readonly', $readonly); 273 | 274 | if($type === 'select' || $type === 'radio' || $type === 'checkboxgroup'){ 275 | $new_options = array(); 276 | 277 | $options = $field->get_property('options'); 278 | if($options && is_array($options)){ 279 | foreach($options as $option){ 280 | $new_option = array(); 281 | $new_option['key'] = $option; 282 | $new_option['text'] = $option; 283 | $new_option['price'] = ''; 284 | $new_option['price_type'] = ''; 285 | 286 | $new_options[$option] = $new_option; 287 | } 288 | } 289 | 290 | $new_options_json = json_encode($new_options); 291 | $new_options_json = rawurlencode($new_options_json); 292 | $new_options_json = trim(stripslashes($new_options_json)); 293 | 294 | $new_field->set_property('options', $new_options); 295 | $new_field->set_property('options_json', $new_options_json); 296 | 297 | }else if($type === 'datepicker'){ 298 | $new_field->set_property('default_date', $value); 299 | 300 | }else if($type === 'heading' || $type === 'label'){ 301 | $new_field->set_property('title', $value); 302 | $new_field->set_property('title_class', $cssclass); 303 | } 304 | 305 | $new_field = self::prepare_conditional_rules($new_field, $conditional_rules); 306 | $new_field = THWEPO_Utils_Field::prepare_properties($new_field); 307 | } 308 | return $new_field; 309 | } 310 | 311 | public static function prepare_conditional_rules($object, $conditional_rules){ 312 | $new_condition_rule_sets = array(); 313 | $cr_sets = array(); 314 | 315 | if($conditional_rules && is_array($conditional_rules)){ 316 | foreach($conditional_rules as $rule_set){ 317 | if($rule_set){ 318 | $logic = $rule_set->get_logic(); 319 | $rules = $rule_set->get_condition_rules(); 320 | 321 | $new_condition_rule_set_obj = new WEPO_Condition_Rule_Set(); 322 | $new_condition_rule_set_obj->set_logic($logic); 323 | 324 | $cr_set = array(); 325 | 326 | if($rules && is_array($rules)){ 327 | foreach($rules as $condition_rule){ 328 | $rule_logic = $condition_rule->get_logic(); 329 | $condition_sets = $condition_rule->get_condition_sets(); 330 | 331 | $new_condition_rule_obj = new WEPO_Condition_Rule(); 332 | $new_condition_rule_obj->set_logic($rule_logic); 333 | 334 | $c_rule = array(); 335 | 336 | if($condition_sets && is_array($condition_sets)){ 337 | foreach($condition_sets as $condition_set){ 338 | $cs_logic = $condition_set->get_logic(); 339 | $conditions = $condition_set->get_conditions(); 340 | 341 | $new_condition_set_obj = new WEPO_Condition_Set(); 342 | $new_condition_set_obj->set_logic($cs_logic); 343 | 344 | $c_set = array(); 345 | 346 | if($conditions && is_array($conditions)){ 347 | foreach($conditions as $condition){ 348 | $subject = $condition->get_subject(); 349 | $comparison = $condition->get_comparison(); 350 | $value = $condition->get_value(); 351 | 352 | $new_condition_obj = new WEPO_Condition(); 353 | $new_condition_obj->set_operand_type($subject); 354 | $new_condition_obj->set_operand($value); 355 | $new_condition_obj->set_operator($comparison); 356 | $new_condition_obj->set_value(''); 357 | 358 | $new_condition_set_obj->add_condition($new_condition_obj); 359 | 360 | $c = array(); 361 | $c['operand_type'] = $subject; 362 | $c['operand'] = $value; 363 | $c['operator'] = $comparison; 364 | $c['value'] = ''; 365 | 366 | array_push($c_set, $c); 367 | } 368 | } 369 | $new_condition_rule_obj->add_condition_set($new_condition_set_obj); 370 | array_push($c_rule, $c_set); 371 | } 372 | } 373 | $new_condition_rule_set_obj->add_condition_rule($new_condition_rule_obj); 374 | array_push($cr_set, $c_rule); 375 | } 376 | } 377 | $new_condition_rule_sets[] = $new_condition_rule_set_obj; 378 | array_push($cr_sets, $cr_set); 379 | } 380 | } 381 | } 382 | 383 | $new_conditional_rules_json = json_encode($cr_sets); 384 | $new_conditional_rules_json = rawurlencode($new_conditional_rules_json); 385 | $new_conditional_rules_json = trim(stripslashes($new_conditional_rules_json)); 386 | 387 | $object->set_property('rules_action', 'show'); 388 | $object->set_property('conditional_rules', $new_condition_rule_sets); 389 | $object->set_property('conditional_rules_json', $new_conditional_rules_json); 390 | 391 | return $object; 392 | } 393 | 394 | public static function may_copy_advanced_settings(){ 395 | $settings = THWEPO_Utils::get_advanced_settings(); 396 | 397 | if(!($settings && is_array($settings))){ 398 | $settings = array(); 399 | $fsettings = get_option('thwepof_advanced_settings'); 400 | 401 | if($fsettings && is_array($fsettings)){ 402 | $settings_mapping = array( 403 | 'add_to_cart_text_addon' => 'add_to_cart_text_addon', 404 | 'add_to_cart_text_simple' => 'add_to_cart_text_simple', 405 | 'add_to_cart_text_variable' => 'add_to_cart_text_variable', 406 | 'hide_in_cart' => 'hide_in_cart', 407 | 'hide_in_checkout' => 'hide_in_checkout', 408 | 'hide_in_order' => 'hide_in_order', 409 | ); 410 | 411 | foreach ($settings_mapping as $fkey => $pkey) { 412 | if(isset($fsettings[$fkey])){ 413 | $settings[$pkey] = $fsettings[$fkey]; 414 | } 415 | } 416 | 417 | if(!empty($settings)){ 418 | $result = update_option(THWEPO_Utils::OPTION_KEY_ADVANCED_SETTINGS, $settings); 419 | } 420 | } 421 | } 422 | } 423 | } 424 | 425 | endif; -------------------------------------------------------------------------------- /includes/class-thwepo-autoloader.php: -------------------------------------------------------------------------------- 1 | 'includes/model/rules/class-wepo-condition.php', 24 | 'wepo_condition_set' => 'includes/model/rules/class-wepo-condition-set.php', 25 | 'wepo_condition_rule' => 'includes/model/rules/class-wepo-rule.php', 26 | 'wepo_condition_rule_set' => 'includes/model/rules/class-wepo-rule-set.php', 27 | 28 | 'wepo_product_page_section' => 'includes/model/class-wepo-section.php', 29 | 'wepo_product_field' => 'includes/model/fields/class-wepo-field.php', 30 | 'wepo_product_field_inputtext' => 'includes/model/fields/class-wepo-field-inputtext.php', 31 | 'wepo_product_field_hidden' => 'includes/model/fields/class-wepo-field-hidden.php', 32 | 'wepo_product_field_password' => 'includes/model/fields/class-wepo-field-password.php', 33 | 'wepo_product_field_number' => 'includes/model/fields/class-wepo-field-number.php', 34 | 'wepo_product_field_tel' => 'includes/model/fields/class-wepo-field-tel.php', 35 | 'wepo_product_field_textarea' => 'includes/model/fields/class-wepo-field-textarea.php', 36 | 'wepo_product_field_select' => 'includes/model/fields/class-wepo-field-select.php', 37 | 'wepo_product_field_multiselect' => 'includes/model/fields/class-wepo-field-multiselect.php', 38 | 'wepo_product_field_radio' => 'includes/model/fields/class-wepo-field-radio.php', 39 | 'wepo_product_field_checkbox' => 'includes/model/fields/class-wepo-field-checkbox.php', 40 | 'wepo_product_field_checkboxgroup' => 'includes/model/fields/class-wepo-field-checkboxgroup.php', 41 | 'wepo_product_field_datepicker' => 'includes/model/fields/class-wepo-field-datepicker.php', 42 | 'wepo_product_field_timepicker' => 'includes/model/fields/class-wepo-field-timepicker.php', 43 | 'wepo_product_field_file' => 'includes/model/fields/class-wepo-field-file.php', 44 | 'wepo_product_field_heading' => 'includes/model/fields/class-wepo-field-heading.php', 45 | 'wepo_product_field_html' => 'includes/model/fields/class-wepo-field-html.php', 46 | 'wepo_product_field_label' => 'includes/model/fields/class-wepo-field-label.php', 47 | 'wepo_product_field_colorpicker' => 'includes/model/fields/class-wepo-field-colorpicker.php', 48 | 49 | 'wepo_wpml_currency_switcher_handler' => 'includes/compatibility/class-wepo-wpml-currency-switcher-handler.php', 50 | ); 51 | 52 | public function __construct() { 53 | $this->include_path = untrailingslashit(THWEPO_PATH); 54 | 55 | if(function_exists("__autoload")){ 56 | spl_autoload_register("__autoload"); 57 | } 58 | spl_autoload_register(array($this, 'autoload')); 59 | } 60 | 61 | /** Include a class file. */ 62 | private function load_file( $path ) { 63 | if ( $path && is_readable( $path ) ) { 64 | require_once( $path ); 65 | return true; 66 | } 67 | return false; 68 | } 69 | 70 | public function autoload_( $class ) { 71 | if(isset($this->class_path[$class])){ 72 | $file = $this->class_path[$class]; 73 | $this->load_file( TH_WEPO_PATH.$file ); 74 | } 75 | } 76 | 77 | /** Class name to file name. */ 78 | private function get_file_name_from_class( $class ) { 79 | return 'class-' . str_replace( '_', '-', $class ) . '.php'; 80 | } 81 | 82 | public function autoload( $class ) { 83 | $class = strtolower( $class ); 84 | $file = $this->get_file_name_from_class( $class ); 85 | $path = ''; 86 | $file_path = ''; 87 | if (isset($this->class_path[$class])){ 88 | $file_path = $this->include_path . '/' . $this->class_path[$class]; 89 | } else { 90 | if (strpos($class, 'thwepo_admin') === 0){ 91 | $path = $this->include_path . '/admin/'; 92 | } elseif (strpos($class, 'thwepo_public') === 0){ 93 | $path = $this->include_path . '/public/'; 94 | } elseif (strpos($class, 'thwepo_utils') === 0){ 95 | $path = $this->include_path . '/includes/utils/'; 96 | } else{ 97 | $path = $this->include_path . '/includes/'; 98 | } 99 | $file_path = $path . $file; 100 | } 101 | 102 | if( empty($file_path) || (!$this->load_file($file_path) && strpos($class, 'thwepo_') === 0) ) { 103 | $this->load_file( $this->include_path . $file ); 104 | } 105 | } 106 | } 107 | 108 | endif; 109 | 110 | new THWEPO_Autoloader(); 111 | -------------------------------------------------------------------------------- /includes/class-thwepo-data.php: -------------------------------------------------------------------------------- 1 | $value_arr, 43 | 'orderby' => 'name', 44 | 'order' => 'ASC', 45 | 'return' => 'ids', 46 | 'limit' => $limit, 47 | ); 48 | $products = $this->get_products($args); 49 | 50 | if(is_array($products) && !empty($products)){ 51 | foreach($products as $pid){ 52 | $productsList[] = array("id" => $pid, "text" => get_the_title($pid), "selected" => true); 53 | } 54 | } 55 | 56 | $count = count($products); 57 | 58 | }else{ 59 | $term = isset($_POST['term']) ? stripslashes($_POST['term']) : ''; 60 | $page = isset($_POST['page']) ? stripslashes($_POST['page']) : 1; 61 | 62 | $status = apply_filters('thwepo_load_products_status', 'publish'); 63 | 64 | $args = array( 65 | 's' => $term, 66 | 'limit' => $limit, 67 | 'page' => $page, 68 | 'status' => $status, 69 | 'orderby' => 'name', 70 | 'order' => 'ASC', 71 | 'return' => 'ids' 72 | ); 73 | $products = $this->get_products($args); 74 | 75 | if(is_array($products) && !empty($products)){ 76 | foreach($products as $pid){ 77 | $productsList[] = array("id" => $pid, "text" => get_the_title($pid)); 78 | //$productsList[] = array("id" => $product->ID, "title" => $product->post_title); 79 | } 80 | } 81 | 82 | $count = count($products); 83 | } 84 | 85 | $morePages = $count < $limit ? false : true; 86 | 87 | $results = array( 88 | "results" => $productsList, 89 | "pagination" => array( "more" => $morePages ) 90 | ); 91 | 92 | wp_send_json_success($results); 93 | die(); 94 | } 95 | 96 | public function get_products($args){ 97 | $products = false; 98 | $is_wpml_active = THWEPO_Utils::is_wpml_active(); 99 | 100 | if($is_wpml_active){ 101 | global $sitepress; 102 | global $icl_adjust_id_url_filter_off; 103 | 104 | $orig_flag_value = $icl_adjust_id_url_filter_off; 105 | $icl_adjust_id_url_filter_off = true; 106 | $default_lang = $sitepress->get_default_language(); 107 | $current_lang = $sitepress->get_current_language(); 108 | $sitepress->switch_lang($default_lang); 109 | 110 | $products = wc_get_products($args); 111 | 112 | $sitepress->switch_lang($current_lang); 113 | $icl_adjust_id_url_filter_off = $orig_flag_value; 114 | }else{ 115 | $products = wc_get_products($args); 116 | } 117 | return $products; 118 | } 119 | 120 | /*public function get_products($only_id = false){ 121 | $skip = $this->skip_products_loading(); 122 | 123 | if(!$skip){ 124 | if(empty($this->products)){ 125 | $this->products = $this->load_products($only_id); 126 | } 127 | } 128 | return $this->products; 129 | }*/ 130 | 131 | /*private function load_products($only_id = false){ 132 | $productsList = array(); 133 | 134 | $limit = apply_filters('thwepo_load_products_per_page', -1); 135 | $status = apply_filters('thwepo_load_products_status', 'publish'); 136 | $only_id = apply_filters('thwepo_load_products_id_only', $only_id); 137 | 138 | $args = array( 139 | 'status' => $status, 140 | 'limit' => $limit, 141 | 'orderby' => 'name', 142 | 'order' => 'ASC', 143 | 'return' => 'ids' 144 | ); 145 | $products = wc_get_products( $args ); 146 | 147 | if(!empty($products)){ 148 | if($only_id){ 149 | return $products; 150 | }else{ 151 | foreach($products as $pid){ 152 | //$productsList[] = array("id" => $product->ID, "title" => $product->post_title); 153 | $productsList[] = array("id" => $pid, "title" => get_the_title($pid)); 154 | } 155 | } 156 | } 157 | return $productsList; 158 | }*/ 159 | 160 | /*private function skip_products_loading(){ 161 | $skip = apply_filters('thwepo_disable_product_dropdown', false); 162 | return $skip; 163 | }*/ 164 | } 165 | 166 | endif; -------------------------------------------------------------------------------- /includes/class-thwepo-deactivator.php: -------------------------------------------------------------------------------- 1 | get_property('minfile'); 42 | $max_count = $field->get_property('maxfile'); 43 | $passed = true; 44 | $title = $field->get_property('title'); 45 | if( empty( $min_count ) && empty( $max_count ) ){ 46 | return true; 47 | } 48 | 49 | if( ( $min_count === $max_count ) && ($min_count !== $file_count ) ){ 50 | THWEPO_Utils::add_error(''.$title.': '. sprintf(THWEPO_i18n::__t('%d files need to be uploaded.'), $min_count ) ); 51 | $passed = false; 52 | 53 | }else if( $file_count < $min_count ){ 54 | THWEPO_Utils::add_error(''.$title.': '. sprintf(THWEPO_i18n::__t('Minimum of %d files need to be uploaded.'), $min_count ) ); 55 | $passed = false; 56 | 57 | }else if( $file_count > $max_count ){ 58 | THWEPO_Utils::add_error(''.$title.': '. sprintf(THWEPO_i18n::__t('Maximum of %d files need to be uploaded.'), $max_count ) ); 59 | $passed = false; 60 | } 61 | return $passed; 62 | } 63 | 64 | public function validate_file($passed, $field, $file){ 65 | if($field->get_property('required') && !$file) { 66 | THWEPO_Utils::add_error( sprintf(THWEPO_i18n::__t('Please select a file for %s'), $field->get_property('title')) ); 67 | $passed = false; 68 | } 69 | $title = THWEPO_Utils_Field::get_display_label($field); 70 | 71 | if($file){ 72 | $file_type = THWEPO_Utils::get_posted_file_type($file); 73 | $file_size = isset($file['size']) ? $file['size'] : false; 74 | 75 | if($file_type && $file_size){ 76 | $name = $field->get_property('name'); 77 | $maxsize = apply_filters('thwepo_file_upload_maxsize', $field->get_property('maxsize'), $name); 78 | $maxsize_bytes = is_numeric($maxsize) ? $maxsize*1048576 : false; 79 | $accept = apply_filters('thwepo_file_upload_accepted_file_types', $field->get_property('accept'), $name); 80 | $accept = $accept && !is_array($accept) ? array_map('trim', explode(",", $accept)) : $accept; 81 | 82 | if(is_array($accept) && !empty($accept) && !in_array($file_type, $accept)){ 83 | THWEPO_Utils::add_error(''.$title.' '. sprintf(THWEPO_i18n::__t('Invalid file type.'))); 84 | $passed = false; 85 | 86 | }else if($maxsize_bytes && is_numeric($maxsize_bytes) && $file_size >= $maxsize_bytes){ 87 | THWEPO_Utils::add_error(''.$title.' '. sprintf(THWEPO_i18n::__t('File too large. File must be less than %s megabytes.'), $maxsize)); 88 | $passed = false; 89 | } 90 | }else if($field->get_property('required')) { 91 | THWEPO_Utils::add_error(''.$title.' '. sprintf(THWEPO_i18n::__t('Please choose a file to upload')) ); 92 | $passed = false; 93 | } 94 | }else if($field->get_property('required')) { 95 | THWEPO_Utils::add_error(''.$title.' '. sprintf(THWEPO_i18n::__t('Please choose a file to upload')) ); 96 | $passed = false; 97 | } 98 | 99 | return $passed; 100 | } 101 | 102 | public function prepare_file_upload( $file, $name, $field ){ 103 | $posted_value = false; 104 | 105 | if(!$field->get_property('required') && !THWEPO_Utils::is_valid_file($file)){ 106 | return false; 107 | } 108 | 109 | $uploaded = $this->upload_file($file, $name, $field); 110 | 111 | if($uploaded && !isset($uploaded['error'])){ 112 | $upload_info = array(); 113 | $upload_info['name'] = $file['name']; 114 | $upload_info['url'] = $uploaded['url']; 115 | 116 | $posted_value = $upload_info; 117 | //$posted_value = $uploaded['url'] . '/' . $file['name']; 118 | }else{ 119 | $title = THWEPO_i18n::__t($field->get_property('title')); 120 | THWEPO_Utils::add_error(''.$title.': '. $uploaded['error']); 121 | return false; 122 | } 123 | return $posted_value; 124 | } 125 | 126 | public function upload_file($file, $name, $field){ 127 | $upload = false; 128 | 129 | if(is_array($file)){ 130 | if(!function_exists('wp_handle_upload')){ 131 | require_once(ABSPATH. 'wp-admin/includes/file.php'); 132 | require_once(ABSPATH. 'wp-admin/includes/media.php'); 133 | } 134 | 135 | add_filter('upload_dir', array('THWEPO_Utils', 'upload_dir')); 136 | //add_filter('upload_mimes', array('THWEPO_Utils', 'upload_mimes')); 137 | $upload = wp_handle_upload($file, array('test_form' => false)); 138 | remove_filter('upload_dir', array('THWEPO_Utils', 'upload_dir')); 139 | //remove_filter('upload_mimes', array('THWEPO_Utils', 'upload_mimes')); 140 | 141 | /*if($upload && !isset($upload['error'])){ 142 | echo "File is valid, and was successfully uploaded.\n"; 143 | } else { 144 | echo $upload['error']; 145 | }*/ 146 | } 147 | return $upload; 148 | } 149 | } 150 | 151 | endif; -------------------------------------------------------------------------------- /includes/class-thwepo-i18n.php: -------------------------------------------------------------------------------- 1 | actions = array(); 42 | $this->filters = array(); 43 | } 44 | 45 | /** 46 | * Add a new action to the collection to be registered with WordPress. 47 | * 48 | * @since 2.3.0 49 | * @param string $hook The name of the WordPress action that is being registered. 50 | * @param object $component A reference to the instance of the object on which the action is defined. 51 | * @param string $callback The name of the function definition on the $component. 52 | * @param int $priority Optional. The priority at which the function should be fired. Default is 10. 53 | * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1. 54 | */ 55 | public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) { 56 | $this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args ); 57 | } 58 | 59 | /** 60 | * Add a new filter to the collection to be registered with WordPress. 61 | * 62 | * @since 2.3.0 63 | * @param string $hook The name of the WordPress filter that is being registered. 64 | * @param object $component A reference to the instance of the object on which the filter is defined. 65 | * @param string $callback The name of the function definition on the $component. 66 | * @param int $priority Optional. The priority at which the function should be fired. Default is 10. 67 | * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1 68 | */ 69 | public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) { 70 | $this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args ); 71 | } 72 | 73 | /** 74 | * A utility function that is used to register the actions and hooks into a single 75 | * collection. 76 | * 77 | * @since 2.3.0 78 | * @access private 79 | * @param array $hooks The collection of hooks that is being registered (that is, actions or filters). 80 | * @param string $hook The name of the WordPress filter that is being registered. 81 | * @param object $component A reference to the instance of the object on which the filter is defined. 82 | * @param string $callback The name of the function definition on the $component. 83 | * @param int $priority The priority at which the function should be fired. 84 | * @param int $accepted_args The number of arguments that should be passed to the $callback. 85 | * @return array The collection of actions and filters registered with WordPress. 86 | */ 87 | private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) { 88 | $hooks[] = array( 89 | 'hook' => $hook, 90 | 'component' => $component, 91 | 'callback' => $callback, 92 | 'priority' => $priority, 93 | 'accepted_args' => $accepted_args 94 | ); 95 | 96 | return $hooks; 97 | } 98 | 99 | /** 100 | * Register the filters and actions with WordPress. 101 | * 102 | * @since 2.3.0 103 | */ 104 | public function run() { 105 | foreach ( $this->filters as $hook ) { 106 | add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] ); 107 | } 108 | 109 | foreach ( $this->actions as $hook ) { 110 | add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] ); 111 | } 112 | } 113 | } 114 | 115 | endif; -------------------------------------------------------------------------------- /includes/class-thwepo.php: -------------------------------------------------------------------------------- 1 | version = THWEPO_VERSION; 56 | } else { 57 | $this->version = '1.0.0'; 58 | } 59 | $this->plugin_name = 'woocommerce-extra-product-options-pro'; 60 | 61 | $this->load_dependencies(); 62 | $this->set_locale(); 63 | $this->define_admin_hooks(); 64 | $this->define_public_hooks(); 65 | 66 | $this->loader->add_action( 'init', $this, 'init' ); 67 | 68 | $this->set_compatibility(); 69 | } 70 | 71 | public function init(){ 72 | $this->define_constants(); 73 | //$this->init_auto_updater(); 74 | } 75 | 76 | private function define_constants(){ 77 | !defined('THWEPO_ASSETS_URL_ADMIN') && define('THWEPO_ASSETS_URL_ADMIN', THWEPO_URL . 'admin/assets/'); 78 | !defined('THWEPO_ASSETS_URL_PUBLIC') && define('THWEPO_ASSETS_URL_PUBLIC', THWEPO_URL . 'public/assets/'); 79 | !defined('THWEPO_WOO_ASSETS_URL') && define('THWEPO_WOO_ASSETS_URL', WC()->plugin_url() . '/assets/'); 80 | } 81 | 82 | /** 83 | * Load the required dependencies for this plugin. 84 | * 85 | * Include the following files that make up the plugin: 86 | * 87 | * - THWEPO_Loader. Orchestrates the hooks of the plugin. 88 | * - THWEPO_i18n. Defines internationalization functionality. 89 | * - THWEPO_Admin. Defines all hooks for the admin area. 90 | * - THWEPO_Public. Defines all hooks for the public side of the site. 91 | * 92 | * Create an instance of the loader which will be used to register the hooks 93 | * with WordPress. 94 | * 95 | * @since 2.3.0 96 | * @access private 97 | */ 98 | private function load_dependencies() { 99 | if(!function_exists('is_plugin_active')){ 100 | include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); 101 | } 102 | 103 | require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-thwepo-autoloader.php'; 104 | 105 | /** 106 | * The class responsible for orchestrating the actions and filters of the 107 | * core plugin. 108 | */ 109 | require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-thwepo-loader.php'; 110 | 111 | /** 112 | * The class responsible for defining internationalization functionality 113 | * of the plugin. 114 | */ 115 | require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-thwepo-i18n.php'; 116 | 117 | /** 118 | * The class responsible for defining all actions that occur in the admin area. 119 | */ 120 | require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-thwepo-admin.php'; 121 | 122 | /** 123 | * The class responsible for defining all actions that occur in the public-facing 124 | * side of the site. 125 | */ 126 | require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-thwepo-public.php'; 127 | 128 | $this->loader = new THWEPO_Loader(); 129 | } 130 | 131 | /** 132 | * Define the locale for this plugin for internationalization. 133 | * 134 | * Uses the THWEPO_i18n class in order to set the domain and to register the hook 135 | * with WordPress. 136 | * 137 | * @since 2.3.0 138 | * @access private 139 | */ 140 | private function set_locale() { 141 | $plugin_i18n = new THWEPO_i18n($this->get_plugin_name()); 142 | $this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' ); 143 | } 144 | 145 | private function init_auto_updater(){ 146 | if(!class_exists('THWEPO_Auto_Update_License') ) { 147 | $api_url = 'https://themehigh.com/'; 148 | require_once plugin_dir_path( dirname( __FILE__ ) ) . 'class-thwepo-auto-update-license.php'; 149 | THWEPO_Auto_Update_License::instance(__FILE__, THWEPO_SOFTWARE_TITLE, THWEPO_VERSION, 'plugin', $api_url, THWEPO_i18n::TEXT_DOMAIN); 150 | } 151 | } 152 | 153 | /** 154 | * Register all of the hooks related to the admin area functionality 155 | * of the plugin. 156 | * 157 | * @since 2.3.0 158 | * @access private 159 | */ 160 | private function define_admin_hooks() { 161 | $plugin_admin = new THWEPO_Admin( $this->get_plugin_name(), $this->get_version() ); 162 | 163 | $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles_and_scripts' ); 164 | $this->loader->add_action( 'admin_menu', $plugin_admin, 'admin_menu' ); 165 | $this->loader->add_filter( 'woocommerce_screen_ids', $plugin_admin, 'add_screen_id' ); 166 | $this->loader->add_filter( 'plugin_action_links_'.THWEPO_BASE_NAME, $plugin_admin, 'plugin_action_links' ); 167 | $this->loader->add_filter( 'plugin_row_meta', $plugin_admin, 'plugin_row_meta', 10, 2 ); 168 | 169 | $wepo_data = THWEPO_Data::instance(); 170 | 171 | $this->loader->add_action('wp_ajax_thwepo_load_products', $wepo_data, 'load_products_ajax'); 172 | $this->loader->add_action('wp_ajax_nopriv_thwepo_load_products', $wepo_data, 'load_products_ajax'); 173 | } 174 | 175 | /** 176 | * Register all of the hooks related to the public-facing functionality 177 | * of the plugin. 178 | * 179 | * @since 2.3.0 180 | * @access private 181 | */ 182 | private function define_public_hooks() { 183 | $plugin_public = new THWEPO_Public( $this->get_plugin_name(), $this->get_version() ); 184 | 185 | $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_styles_and_scripts', 20 ); 186 | } 187 | 188 | /** 189 | * Include files to provide compatibility with requested plugins 190 | * 191 | * 192 | * @since 2.3.0 193 | * @access private 194 | * 195 | * @return null 196 | */ 197 | private function set_compatibility(){ 198 | if( apply_filters( 'thwepo_wpml_currency_swithcer_compatibility', false ) ){ 199 | new WEPO_WPML_Currency_Switcher_Handler(); 200 | } 201 | } 202 | 203 | /** 204 | * Run the loader to execute all of the hooks with WordPress. 205 | * 206 | * @since 2.3.0 207 | */ 208 | public function run() { 209 | $this->loader->run(); 210 | } 211 | 212 | /** 213 | * The name of the plugin used to uniquely identify it within the context of 214 | * WordPress and to define internationalization functionality. 215 | * 216 | * @since 2.3.0 217 | * @return string The name of the plugin. 218 | */ 219 | public function get_plugin_name() { 220 | return $this->plugin_name; 221 | } 222 | 223 | /** 224 | * The reference to the class that orchestrates the hooks with the plugin. 225 | * 226 | * @since 2.3.0 227 | * @return THWEPO_Loader Orchestrates the hooks of the plugin. 228 | */ 229 | public function get_loader() { 230 | return $this->loader; 231 | } 232 | 233 | /** 234 | * Retrieve the version number of the plugin. 235 | * 236 | * @since 2.3.0 237 | * @return string The version number of the plugin. 238 | */ 239 | public function get_version() { 240 | return $this->version; 241 | } 242 | } 243 | 244 | endif; -------------------------------------------------------------------------------- /includes/compatibility/class-wepo-wpml-currency-switcher-handler.php: -------------------------------------------------------------------------------- 1 | 2 | cart_contents as $key => &$value) { 30 | $extra_options = isset($value['thwepo_options']) ? $value['thwepo_options'] : false; 31 | if($extra_options) { 32 | global $woocommerce; 33 | $is_currency_switched = $woocommerce->session->get( 'client_currency_switched'); 34 | $wepo_currency_flag = $woocommerce->session->get( 'wepo_client_currency_switched'); 35 | if($is_currency_switched && $wepo_currency_flag){ 36 | $value['thwepo-original_price'] = $value['data']->get_price(''); 37 | $woocommerce->session->set( 'wepo_client_currency_switched', false ); 38 | } 39 | } 40 | } 41 | 42 | } 43 | 44 | public function wpml_currency_val($price, $name, $price_info, $product_info){ 45 | if($price){ 46 | $price = $this->convert_price_as_per_currency_used($price); 47 | } 48 | 49 | return $price; 50 | } 51 | 52 | public function wpml_currency_swictched(){ 53 | global $woocommerce; 54 | $woocommerce->session->set( 'wepo_client_currency_switched', true ); 55 | } 56 | 57 | public function add_action_to_multi_currency_ajax( $array ) { 58 | $array[] = 'thwepo_calculate_extra_cost'; // Add a AJAX action to the array 59 | return $array; 60 | } 61 | 62 | public function change_display_price_as_per_currency($price, $product_price, $price_type){ 63 | if($price){ 64 | $price = $this->convert_price_as_per_currency_used($price); 65 | } 66 | 67 | return $price; 68 | } 69 | 70 | public function change_option_price($price, $price_type, $option, $name){ 71 | if($price){ 72 | $price = $this->convert_price_as_per_currency_used($price); 73 | } 74 | 75 | return $price; 76 | } 77 | 78 | public function is_woocommmerce_wpml_actice(){ 79 | $is_currency_switcher_active = is_plugin_active('woocommerce-multilingual/wpml-woocommerce.php'); 80 | return $is_currency_switcher_active; 81 | } 82 | 83 | public function convert_price_as_per_currency_used($price){ 84 | global $woocommerce, $woocommerce_wpml; 85 | $is_active = is_woocommmerce_wpml_actice(); 86 | 87 | if($price && $is_active){ 88 | $multi_currency = $woocommerce_wpml->get_multi_currency(); 89 | if($multi_currency){ 90 | $currency_settings = $woocommerce_wpml->get_setting( 'currency_options' ); 91 | $currecy_switcher = new WCML_Multi_Currency_Prices($multi_currency, $currency_settings); 92 | 93 | if($currecy_switcher){ 94 | $price = $currecy_switcher->raw_price_filter($price); 95 | } 96 | } 97 | } 98 | 99 | return $price; 100 | } 101 | } 102 | 103 | endif; -------------------------------------------------------------------------------- /includes/index.php: -------------------------------------------------------------------------------- 1 | $name = $value; 62 | } 63 | } 64 | 65 | public function get_property($name){ 66 | if(property_exists($this, $name)){ 67 | return $this->$name; 68 | }else{ 69 | return ''; 70 | } 71 | } 72 | } 73 | 74 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-checkbox.php: -------------------------------------------------------------------------------- 1 | type = 'checkbox'; 20 | } 21 | } 22 | 23 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-checkboxgroup.php: -------------------------------------------------------------------------------- 1 | type = 'checkboxgroup'; 20 | } 21 | } 22 | 23 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-colorpicker.php: -------------------------------------------------------------------------------- 1 | type = 'colorpicker'; 23 | } 24 | } 25 | 26 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-datepicker.php: -------------------------------------------------------------------------------- 1 | type = 'datepicker'; 39 | } 40 | } 41 | 42 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-factory.php: -------------------------------------------------------------------------------- 1 | type = 'file'; 24 | } 25 | } 26 | 27 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-heading.php: -------------------------------------------------------------------------------- 1 | type = 'heading'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-hidden.php: -------------------------------------------------------------------------------- 1 | type = 'hidden'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-html.php: -------------------------------------------------------------------------------- 1 | type = 'html'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-inputtext.php: -------------------------------------------------------------------------------- 1 | type = 'inputtext'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-label.php: -------------------------------------------------------------------------------- 1 | type = 'label'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-multiselect.php: -------------------------------------------------------------------------------- 1 | type = 'multiselect'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-number.php: -------------------------------------------------------------------------------- 1 | type = 'number'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-password.php: -------------------------------------------------------------------------------- 1 | type = 'password'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-radio.php: -------------------------------------------------------------------------------- 1 | type = 'radio'; 20 | } 21 | } 22 | 23 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-select.php: -------------------------------------------------------------------------------- 1 | type = 'select'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-tel.php: -------------------------------------------------------------------------------- 1 | type = 'tel'; 18 | } 19 | } 20 | 21 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-textarea.php: -------------------------------------------------------------------------------- 1 | type = 'textarea'; 21 | } 22 | } 23 | 24 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field-timepicker.php: -------------------------------------------------------------------------------- 1 | type = 'timepicker'; 23 | } 24 | } 25 | 26 | endif; -------------------------------------------------------------------------------- /includes/model/fields/class-wepo-field.php: -------------------------------------------------------------------------------- 1 | $name = $value; 94 | } 95 | 96 | public function get_property($name){ 97 | $value = ''; 98 | 99 | if(property_exists($this, $name)){ 100 | $value = $this->$name; 101 | } 102 | 103 | return apply_filters( 'thwepo_field_property_value', $value, $name, $this ); 104 | } 105 | } 106 | 107 | endif; -------------------------------------------------------------------------------- /includes/model/rules/class-wepo-condition-set.php: -------------------------------------------------------------------------------- 1 | get_conditions(); 29 | if(!empty($conditions)){ 30 | if($this->get_logic() === self::LOGIC_AND){ 31 | foreach($conditions as $condition){ 32 | if(!$condition->is_satisfied($product, $categories, $tags)){ 33 | $satisfied = false; 34 | break; 35 | } 36 | } 37 | }else if($this->get_logic() === self::LOGIC_OR){ 38 | $satisfied = false; 39 | foreach($conditions as $condition){ 40 | if($condition->is_satisfied($product, $categories, $tags)){ 41 | $satisfied = true; 42 | break; 43 | } 44 | } 45 | } 46 | } 47 | return $satisfied; 48 | } 49 | 50 | public function add_condition($condition){ 51 | if(isset($condition) && $condition instanceof WEPO_Condition && $condition->is_valid()){ 52 | $this->conditions[] = $condition; 53 | } 54 | } 55 | 56 | public function set_logic($logic){ 57 | $this->logic = $logic; 58 | } 59 | public function get_logic(){ 60 | return $this->logic; 61 | } 62 | 63 | public function set_conditions($conditions){ 64 | $this->conditions = $conditions; 65 | } 66 | public function get_conditions(){ 67 | return $this->conditions; 68 | } 69 | } 70 | 71 | endif; -------------------------------------------------------------------------------- /includes/model/rules/class-wepo-condition.php: -------------------------------------------------------------------------------- 1 | operand_type) && !empty($this->operator)){ 43 | return true; 44 | } 45 | return false; 46 | } 47 | 48 | public function is_satisfied($product, $categories, $tags=false){ 49 | $satisfied = true; 50 | if($this->is_valid()){ 51 | $operands = $this->operand; 52 | 53 | if(!empty($operands) && !in_array(-1, $operands)){ 54 | if($this->operand_type == self::PRODUCT){ 55 | if($this->operator == self::EQUALS) { 56 | if(!in_array($product, $operands)){ 57 | return false; 58 | } 59 | }else if($this->operator == self::NOT_EQUALS){ 60 | if(in_array($product, $operands)){ 61 | return false; 62 | } 63 | } 64 | }else if($this->operand_type == self::CATEGORY){ 65 | $commonCategories = array_intersect($categories, $operands); 66 | 67 | if($this->operator == self::EQUALS) { 68 | if(empty($commonCategories)){ 69 | return false; 70 | } 71 | }else if($this->operator == self::NOT_EQUALS){ 72 | if(!empty($commonCategories)){ 73 | return false; 74 | } 75 | } 76 | }else if($this->subject == self::TAG){ 77 | $commonTags = array_intersect($tags, $operands); 78 | 79 | if($this->operator == self::EQUALS) { 80 | if(empty($commonTags)){ 81 | return false; 82 | } 83 | }else if($this->operator == self::NOT_EQUALS){ 84 | if(!empty($commonTags)){ 85 | return false; 86 | } 87 | } 88 | } 89 | } 90 | } 91 | return $satisfied; 92 | } 93 | 94 | public function set_operand_type($operand_type){ 95 | $this->operand_type = $operand_type; 96 | } 97 | public function get_operand_type(){ 98 | return $this->operand_type; 99 | } 100 | 101 | public function set_operand($operand){ 102 | $this->operand = $operand; 103 | } 104 | public function get_operand(){ 105 | return $this->operand; 106 | } 107 | 108 | public function set_operator($operator){ 109 | $this->operator = $operator; 110 | } 111 | public function get_operator(){ 112 | return $this->operator; 113 | } 114 | 115 | public function set_value($value){ 116 | $this->value = $value; 117 | } 118 | public function get_value(){ 119 | return $this->value; 120 | } 121 | } 122 | 123 | endif; -------------------------------------------------------------------------------- /includes/model/rules/class-wepo-rule-set.php: -------------------------------------------------------------------------------- 1 | get_condition_rules(); 29 | if(!empty($condition_rules)){ 30 | if($this->get_logic() === self::LOGIC_AND){ 31 | foreach($condition_rules as $condition_rule){ 32 | if(!$condition_rule->is_satisfied($product, $categories, $tags)){ 33 | $satisfied = false; 34 | break; 35 | } 36 | } 37 | }else if($this->get_logic() === self::LOGIC_OR){ 38 | $satisfied = false; 39 | foreach($condition_rules as $condition_rule){ 40 | if($condition_rule->is_satisfied($product, $categories, $tags)){ 41 | $satisfied = true; 42 | break; 43 | } 44 | } 45 | } 46 | } 47 | return $satisfied; 48 | } 49 | 50 | public function add_condition_rule($condition_rule){ 51 | if(isset($condition_rule) && $condition_rule instanceof WEPO_Condition_Rule){ 52 | $this->condition_rules[] = $condition_rule; 53 | } 54 | } 55 | 56 | public function set_logic($logic){ 57 | $this->logic = $logic; 58 | } 59 | public function get_logic(){ 60 | return $this->logic; 61 | } 62 | 63 | public function set_condition_rules($condition_rules){ 64 | $this->condition_rules = $condition_rules; 65 | } 66 | public function get_condition_rules(){ 67 | return $this->condition_rules; 68 | } 69 | } 70 | 71 | endif; -------------------------------------------------------------------------------- /includes/model/rules/class-wepo-rule.php: -------------------------------------------------------------------------------- 1 | get_condition_sets(); 29 | if(!empty($condition_sets)){ 30 | if($this->get_logic() === self::LOGIC_AND){ 31 | foreach($condition_sets as $condition_set){ 32 | if(!$condition_set->is_satisfied($product, $categories, $tags)){ 33 | $satisfied = false; 34 | break; 35 | } 36 | } 37 | }else if($this->get_logic() === self::LOGIC_OR){ 38 | $satisfied = false; 39 | foreach($condition_sets as $condition_set){ 40 | if($condition_set->is_satisfied($product, $categories, $tags)){ 41 | $satisfied = true; 42 | break; 43 | } 44 | } 45 | } 46 | } 47 | return $satisfied; 48 | } 49 | 50 | public function add_condition_set($condition_set){ 51 | if(isset($condition_set) && $condition_set instanceof WEPO_Condition_Set){ 52 | $this->condition_sets[] = $condition_set; 53 | } 54 | } 55 | 56 | public function set_logic($logic){ 57 | $this->logic = $logic; 58 | } 59 | public function get_logic(){ 60 | return $this->logic; 61 | } 62 | 63 | public function set_condition_sets($condition_sets){ 64 | $this->condition_sets = $condition_sets; 65 | } 66 | public function get_condition_sets(){ 67 | return $this->condition_sets; 68 | } 69 | } 70 | 71 | endif; -------------------------------------------------------------------------------- /includes/utils/class-thwepo-utils-condition.php: -------------------------------------------------------------------------------- 1 | operand_type) && !empty($condition->operator)){ 33 | return true; 34 | } 35 | return false; 36 | } 37 | 38 | public static function is_satisfied($rules_set_list, $product, $categories, $tags=false){ 39 | $valid = true; 40 | if(is_array($rules_set_list) && !empty($rules_set_list)){ 41 | foreach($rules_set_list as $rules_set){ 42 | if(!self::is_satisfied_rules_set($rules_set, $product, $categories, $tags)){ 43 | $valid = false; 44 | } 45 | } 46 | } 47 | return $valid; 48 | } 49 | 50 | private static function is_satisfied_condition($condition, $product, $categories, $tags){ 51 | $satisfied = true; 52 | if(self::is_valid_condition($condition)){ 53 | $op_type = $condition->operand_type; 54 | $operator = $condition->operator; 55 | $operands = $condition->operand; 56 | 57 | if(!empty($operands) && !in_array(-1, $operands)){ 58 | if($op_type == self::OP_TYPE_PRODUCT){ 59 | $product = THWEPO_Utils::get_original_product_id($product); 60 | 61 | if($operator == self::OPERATOR_EQUALS) { 62 | if(!in_array($product, $operands)){ 63 | return false; 64 | } 65 | }else if($operator == self::OPERATOR_NOT_EQUALS){ 66 | if(in_array($product, $operands)){ 67 | return false; 68 | } 69 | } 70 | }else if($op_type == self::OP_TYPE_CATEGORY){ 71 | $commonCategories = array_intersect($categories, $operands); 72 | 73 | if($operator == self::OPERATOR_EQUALS) { 74 | if(empty($commonCategories)){ 75 | return false; 76 | } 77 | }else if($operator == self::OPERATOR_NOT_EQUALS){ 78 | if(!empty($commonCategories)){ 79 | return false; 80 | } 81 | } 82 | }else if($op_type == self::OP_TYPE_TAG){ 83 | $commonTags = array_intersect($tags, $operands); 84 | 85 | if($operator == self::OPERATOR_EQUALS) { 86 | if(empty($commonTags)){ 87 | return false; 88 | } 89 | }else if($operator == self::OPERATOR_NOT_EQUALS){ 90 | if(!empty($commonTags)){ 91 | return false; 92 | } 93 | } 94 | }else if($op_type === self::OP_TYPE_USER){ 95 | $user_roles = THWEPO_Utils::get_user_roles(); 96 | 97 | if(is_array($user_roles) && is_array($operands)){ 98 | $intersection = array_intersect($user_roles, $operands); 99 | 100 | if($operator == self::OPERATOR_EQUALS) { 101 | if(empty($intersection)){ 102 | return false; 103 | } 104 | }else if($operator == self::OPERATOR_NOT_EQUALS){ 105 | if(!empty($intersection)){ 106 | return false; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | } 113 | return $satisfied; 114 | } 115 | 116 | private static function is_satisfied_rules_set($rules_set, $product, $categories, $tags){ 117 | $satisfied = true; 118 | $condition_rules = $rules_set->get_condition_rules(); 119 | $logic = $rules_set->get_logic(); 120 | 121 | if(!empty($condition_rules)){ 122 | if($logic === self::LOGIC_AND){ 123 | foreach($condition_rules as $condition_rule){ 124 | if(!self::is_satisfied_rule($condition_rule, $product, $categories, $tags)){ 125 | $satisfied = false; 126 | break; 127 | } 128 | } 129 | }else if($logic === self::LOGIC_OR){ 130 | $satisfied = false; 131 | foreach($condition_rules as $condition_rule){ 132 | if(self::is_satisfied_rule($condition_rule, $product, $categories, $tags)){ 133 | $satisfied = true; 134 | break; 135 | } 136 | } 137 | } 138 | } 139 | return $satisfied; 140 | } 141 | 142 | private static function is_satisfied_rule($rule, $product, $categories, $tags){ 143 | $satisfied = true; 144 | $conditions_set_list = $rule->get_condition_sets(); 145 | $logic = $rule->get_logic(); 146 | 147 | if(!empty($conditions_set_list)){ 148 | if($logic === self::LOGIC_AND){ 149 | foreach($conditions_set_list as $conditions_set){ 150 | if(!self::is_satisfied_conditions_set($conditions_set, $product, $categories, $tags)){ 151 | $satisfied = false; 152 | break; 153 | } 154 | } 155 | }else if($logic === self::LOGIC_OR){ 156 | $satisfied = false; 157 | foreach($conditions_set_list as $conditions_set){ 158 | if(self::is_satisfied_conditions_set($conditions_set, $product, $categories, $tags)){ 159 | $satisfied = true; 160 | break; 161 | } 162 | } 163 | } 164 | } 165 | return $satisfied; 166 | } 167 | 168 | private static function is_satisfied_conditions_set($conditions_set, $product, $categories, $tags){ 169 | $satisfied = true; 170 | $conditions = $conditions_set->get_conditions(); 171 | $logic = $conditions_set->get_logic(); 172 | 173 | if(!empty($conditions)){ 174 | if($logic === self::LOGIC_AND){ 175 | foreach($conditions as $condition){ 176 | if(!self::is_satisfied_condition($condition, $product, $categories, $tags)){ 177 | $satisfied = false; 178 | break; 179 | } 180 | } 181 | }else if($logic === self::LOGIC_OR){ 182 | $satisfied = false; 183 | foreach($conditions as $condition){ 184 | if(self::is_satisfied_condition($condition, $product, $categories, $tags)){ 185 | $satisfied = true; 186 | break; 187 | } 188 | } 189 | } 190 | } 191 | return $satisfied; 192 | } 193 | 194 | public static function prepare_conditional_rules($posted, $ajax=false){ 195 | $iname = $ajax ? 'i_rules_ajax' : 'i_rules'; 196 | $conditional_rules = isset($posted[$iname]) ? trim(stripslashes($posted[$iname])) : ''; 197 | 198 | $condition_rule_sets = array(); 199 | if(!empty($conditional_rules)){ 200 | $conditional_rules = urldecode($conditional_rules); 201 | $rule_sets = json_decode($conditional_rules, true); 202 | 203 | if(is_array($rule_sets)){ 204 | foreach($rule_sets as $rule_set){ 205 | if(is_array($rule_set)){ 206 | $condition_rule_set_obj = new WEPO_Condition_Rule_Set(); 207 | $condition_rule_set_obj->set_logic('and'); 208 | 209 | foreach($rule_set as $condition_sets){ 210 | if(is_array($condition_sets)){ 211 | $condition_rule_obj = new WEPO_Condition_Rule(); 212 | $condition_rule_obj->set_logic('or'); 213 | 214 | foreach($condition_sets as $condition_set){ 215 | if(is_array($condition_set)){ 216 | $condition_set_obj = new WEPO_Condition_Set(); 217 | $condition_set_obj->set_logic('and'); 218 | 219 | foreach($condition_set as $condition){ 220 | if(is_array($condition)){ 221 | $condition_obj = new WEPO_Condition(); 222 | $condition_obj->set_operand_type(isset($condition['operand_type']) ? $condition['operand_type'] : ''); 223 | $condition_obj->set_operand(isset($condition['operand']) ? $condition['operand'] : ''); 224 | $condition_obj->set_operator(isset($condition['operator']) ? $condition['operator'] : ''); 225 | $condition_obj->set_value(isset($condition['value']) ? trim($condition['value']) : ''); 226 | 227 | $condition_set_obj->add_condition($condition_obj); 228 | } 229 | } 230 | $condition_rule_obj->add_condition_set($condition_set_obj); 231 | } 232 | } 233 | $condition_rule_set_obj->add_condition_rule($condition_rule_obj); 234 | } 235 | } 236 | $condition_rule_sets[] = $condition_rule_set_obj; 237 | } 238 | } 239 | } 240 | } 241 | return $condition_rule_sets; 242 | } 243 | } 244 | 245 | endif; -------------------------------------------------------------------------------- /includes/utils/class-thwepo-utils-core.php: -------------------------------------------------------------------------------- 1 | array('name'=>'name', 'value'=>''), 19 | 'position' => array('name'=>'position', 'value'=>''), 20 | 'order' => array('name'=>'order', 'value'=>''), 21 | 'cssclass' => array('name'=>'cssclass', 'value'=>array(), 'value_type'=>'array'), 22 | 23 | 'title_cell_with' => array('name'=>'title_cell_with', 'value'=>''), 24 | 'field_cell_with' => array('name'=>'field_cell_with', 'value'=>''), 25 | 26 | 'show_title' => array('name'=>'show_title', 'value'=>1, 'value_type'=>'boolean'), 27 | //'custom_section' => array('name'=>'custom_section', 'value'=>1, 'value_type'=>'boolean'), 28 | 29 | 'title' => array('name'=>'title', 'value'=>''), 30 | 'title_type' => array('name'=>'title_type', 'value'=>''), 31 | 'title_color' => array('name'=>'title_color', 'value'=>''), 32 | 'title_position' => array('name'=>'title_position', 'value'=>''), 33 | 'title_class' => array('name'=>'title_class', 'value'=>array(), 'value_type'=>'array'), 34 | 35 | 'subtitle' => array('name'=>'subtitle', 'value'=>''), 36 | 'subtitle_type' => array('name'=>'subtitle_type', 'value'=>''), 37 | 'subtitle_color' => array('name'=>'subtitle_color', 'value'=>''), 38 | 'subtitle_position' => array('name'=>'subtitle_position', 'value'=>''), 39 | 'subtitle_class' => array('name'=>'subtitle_class', 'value'=>array(), 'value_type'=>'array'), 40 | ); 41 | 42 | public static function is_valid_section($section){ 43 | if(isset($section) && $section instanceof WEPO_Product_Page_Section && !empty($section->name)){ 44 | return true; 45 | } 46 | return false; 47 | } 48 | 49 | public static function is_enabled($section){ 50 | if($section->get_property('enabled')){ 51 | return true; 52 | } 53 | return false; 54 | } 55 | 56 | public static function is_custom_section($section){ 57 | //return $section->custom_section; 58 | return true; 59 | } 60 | 61 | public static function has_fields($section){ 62 | if($section->get_property('fields')){ 63 | return true; 64 | } 65 | return false; 66 | } 67 | 68 | public static function is_show_section($section, $product, $categories, $tags=false){ 69 | /*$show = true; 70 | if(!empty($condition_sets)){ 71 | foreach($condition_sets as $condition_set){ 72 | if($condition_set->show_element()){ 73 | $show = false; 74 | } 75 | } 76 | } 77 | 78 | return $show;*/ 79 | 80 | $rules_set_list = $section->get_property('conditional_rules'); 81 | $valid = THWEPO_Utils_Condition::is_satisfied($rules_set_list, $product, $categories, $tags); 82 | 83 | $show = true; 84 | if($section->get_property('rules_action') === 'hide'){ 85 | $show = $valid ? false : true; 86 | }else{ 87 | $show = $valid ? true : false; 88 | } 89 | $show = apply_filters('thwepo_show_section', $show, $section->name); 90 | return $show; 91 | } 92 | 93 | public static function prepare_default_section(){ 94 | $section = new WEPO_Product_Page_Section(); 95 | $section->set_property('id', 'default'); 96 | $section->set_property('name', 'default'); 97 | $section->set_property('title', 'Default'); 98 | $section->set_property('show_title', 0); 99 | $section->set_property('position', 'woo_before_add_to_cart_button'); 100 | 101 | return $section; 102 | } 103 | 104 | public static function prepare_section_from_posted_data($posted, $form = 'new'){ 105 | $name = isset($posted['i_name']) ? $posted['i_name'] : ''; 106 | $position = isset($posted['i_position']) ? $posted['i_position'] : ''; 107 | $title = isset($posted['i_title']) ? $posted['i_title'] : ''; 108 | 109 | if(!$name || !$title || !$position){ 110 | return; 111 | } 112 | 113 | if($form === 'edit'){ 114 | $section = THWEPO_Admin_Utils::get_section($name); 115 | }else{ 116 | $name = strtolower($name); 117 | $name = is_numeric($name) ? "s_".$name : $name; 118 | 119 | $section = new WEPO_Product_Page_Section(); 120 | $section->set_property('id', $name); 121 | } 122 | 123 | foreach( self::$SECTION_PROPS as $pname => $property ){ 124 | $iname = 'i_'.$pname; 125 | $pvalue = isset($posted[$iname]) ? trim(stripslashes($posted[$iname])) : $property['value']; 126 | 127 | if($pname === 'show_title'){ 128 | $pvalue = !empty($pvalue) && $pvalue === 'yes' ? 1 : 0; 129 | } 130 | 131 | $section->set_property($pname, $pvalue); 132 | } 133 | 134 | $section->set_property('custom_section', 1); 135 | 136 | $section->set_property('rules_action', isset($posted['i_rules_action']) ? trim(stripslashes($posted['i_rules_action'])) : ''); 137 | $section->set_property('conditional_rules_json', isset($posted['i_rules']) ? trim(stripslashes($posted['i_rules'])) : ''); 138 | $section->set_property('conditional_rules', THWEPO_Utils_Condition::prepare_conditional_rules($posted, false)); 139 | 140 | $section->set_property('rules_action_ajax', isset($posted['i_rules_action_ajax']) ? trim(stripslashes($posted['i_rules_action_ajax'])) : ''); 141 | $section->set_property('conditional_rules_ajax_json', isset($posted['i_rules_ajax']) ? trim(stripslashes($posted['i_rules_ajax'])) : ''); 142 | $section->set_property('conditional_rules_ajax', THWEPO_Utils_Condition::prepare_conditional_rules($posted, true)); 143 | 144 | //WPML Support 145 | self::add_wpml_support($section); 146 | return $section; 147 | } 148 | 149 | public static function get_property_set($section){ 150 | if(self::is_valid_section($section)){ 151 | $props_set = array(); 152 | 153 | foreach(self::$SECTION_PROPS as $pname => $props){ 154 | $pvalue = $section->get_property($props['name']); 155 | 156 | if(isset($props['value_type']) && $props['value_type'] === 'array' && !empty($pvalue)){ 157 | $pvalue = is_array($pvalue) ? $pvalue : explode(',', $pvalue); 158 | } 159 | 160 | if(isset($props['value_type']) && $props['value_type'] != 'boolean'){ 161 | $pvalue = empty($pvalue) ? $props['value'] : $pvalue; 162 | } 163 | 164 | $props_set[$pname] = $pvalue; 165 | } 166 | 167 | $props_set['custom'] = self::is_custom_section($section); 168 | $props_set['rules_action'] = $section->get_property('rules_action'); 169 | $props_set['rules_action_ajax'] = $section->get_property('rules_action_ajax'); 170 | 171 | return $props_set; 172 | }else{ 173 | return false; 174 | } 175 | } 176 | 177 | public static function get_property_json($section){ 178 | $props_json = ''; 179 | $props_set = self::get_property_set($section); 180 | 181 | if($props_set){ 182 | $props_json = json_encode($props_set); 183 | } 184 | return $props_json; 185 | } 186 | 187 | public static function add_field($section, $field){ 188 | if(self::is_valid_section($section) && THWEPO_Utils_Field::is_valid_field($field)){ 189 | $size = sizeof($section->fields); 190 | $field->set_property('order', $size); 191 | $field->set_property('custom_field', 1); 192 | $section->fields[$field->get_property('name')] = $field; 193 | return $section; 194 | }else{ 195 | throw new Exception('Invalid Section or Field Object.'); 196 | } 197 | } 198 | 199 | public static function update_field($section, $field){ 200 | if(self::is_valid_section($section) && THWEPO_Utils_Field::is_valid_field($field)){ 201 | $name = $field->get_property('name'); 202 | $name_old = $field->get_property('name_old'); 203 | $field_set = $section->fields; 204 | 205 | if(!empty($name) && is_array($field_set) && isset($field_set[$name_old])){ 206 | $o_field = $field_set[$name_old]; 207 | //$index = array_search($name_old, array_keys($field_set)); 208 | $field->set_property('order', $o_field->get_property('order')); 209 | $field->set_property('custom_field', $o_field->get_property('custom_field')); 210 | $field_set[$name] = $field; 211 | 212 | if($name != $name_old){ 213 | unset($field_set[$name_old]); 214 | } 215 | $field_set = self::sort_field_set($field_set); 216 | $section->set_property('fields', $field_set); 217 | } 218 | return $section; 219 | }else{ 220 | throw new Exception('Invalid Section or Field Object.'); 221 | } 222 | } 223 | 224 | public static function get_fields($section, $ignore_disabled=false){ 225 | $fields = (is_array($section->fields) && !empty($section->fields)) ? $section->fields : array(); 226 | 227 | if($ignore_disabled && is_array($fields)){ 228 | foreach($fields as $key => $field){ 229 | if(!THWEPO_Utils_Field::is_enabled($field)){ 230 | unset($fields[$key]); 231 | } 232 | } 233 | } 234 | return $fields; 235 | } 236 | 237 | public static function get_product_sections_and_fields($product){ 238 | $product_id = THWEPO_Utils::get_product_id($product); 239 | $categories = THWEPO_Utils::get_product_categories($product_id); 240 | $tags = THWEPO_Utils::get_product_tags($product_id); 241 | $sections = THWEPO_Utils::get_custom_sections(); 242 | 243 | if($sections && is_array($sections) && !empty($sections)){ 244 | foreach($sections as $section_name => $section){ 245 | $section = self::prepare_section_and_fields($section, $product_id, $categories, $tags); 246 | if($section){ 247 | $sections[$section_name] = $section; 248 | }else{ 249 | unset($sections[$section_name]); 250 | } 251 | } 252 | } 253 | return $sections; 254 | } 255 | 256 | /** 257 | * Check and filter invalid, disabled and conditionally hidden section and fields. 258 | * 259 | * @param $section 260 | * @param $product_id 261 | * @param $categories 262 | * @param $tags 263 | * 264 | * @return $section - A cleaned Section object 265 | */ 266 | public static function prepare_section_and_fields($section, $product_id, $categories, $tags=false){ 267 | if(self::is_valid_section($section) && self::is_show_section($section, $product_id, $categories, $tags)){ 268 | $fields = self::get_fields($section); 269 | if(is_array($fields)){ 270 | foreach($fields as $field_name => $field){ 271 | if(THWEPO_Utils_Field::is_enabled($field) && THWEPO_Utils_Field::is_show_field($field, $product_id, $categories, $tags)){ 272 | $fields[$field_name] = $field; 273 | }else{ 274 | unset($fields[$field_name]); 275 | } 276 | } 277 | 278 | if(!empty($fields)){ 279 | $section->set_property('fields', $fields); 280 | return $section; 281 | } 282 | } 283 | } 284 | return false; 285 | } 286 | 287 | public static function get_product_fields($product, $names_only = true){ 288 | $product_id = THWEPO_Utils::get_product_id($product); 289 | $categories = THWEPO_Utils::get_product_categories($product_id); 290 | $tags = THWEPO_Utils::get_product_tags($product_id); 291 | $sections = THWEPO_Utils::get_custom_sections(); 292 | $prod_fields = array(); 293 | 294 | if($sections && is_array($sections) && !empty($sections)){ 295 | foreach($sections as $section_name => $section){ 296 | $fields = self::get_product_section_fields($section, $product_id, $categories, $tags, $names_only); 297 | if($fields){ 298 | $prod_fields = array_merge($prod_fields, $fields); 299 | } 300 | } 301 | } 302 | return $prod_fields; 303 | } 304 | 305 | public static function get_product_section_fields($section, $product_id, $categories, $tags=false, $names_only = true){ 306 | $prod_fields = array(); 307 | if(self::is_valid_section($section) && self::is_show_section($section, $product_id, $categories, $tags)){ 308 | $fields = self::get_fields($section); 309 | 310 | if(is_array($fields)){ 311 | foreach($fields as $field_name => $field){ 312 | if(THWEPO_Utils_Field::is_enabled($field) && THWEPO_Utils_Field::is_show_field($field, $product_id, $categories, $tags)){ 313 | if($names_only){ 314 | $prod_fields[] = $field_name; 315 | }else{ 316 | $prod_fields[$field_name] = $field; 317 | } 318 | } 319 | } 320 | } 321 | } 322 | return $prod_fields; 323 | } 324 | 325 | public static function clear_fields($section){ 326 | if(self::is_valid_section($section)){ 327 | $section->fields = array(); 328 | } 329 | return $section; 330 | } 331 | 332 | public static function sort_fields($section){ 333 | uasort($section->fields, array('self', 'sort_by_order')); 334 | return $section; 335 | } 336 | 337 | public static function sort_field_set($field_set){ 338 | uasort($field_set, array('self', 'sort_by_order')); 339 | return $field_set; 340 | } 341 | 342 | public static function sort_by_order($a, $b){ 343 | if($a->get_property('order') == $b->get_property('order')){ 344 | return 0; 345 | } 346 | return ($a->get_property('order') < $b->get_property('order')) ? -1 : 1; 347 | } 348 | 349 | public static function add_wpml_support($section){ 350 | THWEPO_i18n::wpml_register_string('Section Title - '.$section->name, $section->title ); 351 | THWEPO_i18n::wpml_register_string('Section Subtitle - '.$section->name, $section->subtitle ); 352 | } 353 | 354 | /*********************************************** 355 | *********** DISPLAY SECTIONS - START ********** 356 | ***********************************************/ 357 | public static function prepare_section_html($section, $product_type = false){ 358 | $field_html = ''; 359 | $field_html_hidden = ''; 360 | $section_html = ''; 361 | 362 | $fields = self::get_fields($section); 363 | if(is_array($fields)){ 364 | foreach($fields as $field){ 365 | if($field->get_property('type') === 'hidden'){ 366 | $field_html_hidden .= THWEPO_Utils_Field::prepare_field_html($field, $section); 367 | }else{ 368 | $field_html .= THWEPO_Utils_Field::prepare_field_html($field, $section); 369 | } 370 | } 371 | } 372 | 373 | if(!empty($field_html)){ 374 | $cssclass = THWEPO_Utils::convert_cssclass_string($section->get_property('cssclass')); 375 | $cssclass .= $product_type ? ' thwepo_'.$product_type : ''; 376 | 377 | $conditions_data = self::get_ajax_conditions_data($section); 378 | if($conditions_data){ 379 | $cssclass .= empty($cssclass) ? 'thwepo-conditional-section' : ' thwepo-conditional-section'; 380 | } 381 | 382 | $section_html .= ''; 383 | $section_html .= $section->get_property('show_title') ? self::prepare_title_html($section) : ''; 384 | $section_html .= $field_html; 385 | $section_html .= '
    '; 386 | } 387 | 388 | if(!empty($field_html_hidden)){ 389 | $section_html .= $field_html_hidden; 390 | } 391 | return $section_html; 392 | } 393 | 394 | public static function prepare_title_html($section){ 395 | $title_html = ''; 396 | if($section->get_property('title')){ 397 | $title_class = THWEPO_Utils::convert_cssclass_string($section->get_property('title_class')); 398 | $title_type = $section->get_property('title_type') ? $section->get_property('title_type') : 'label'; 399 | $title_style = $section->get_property('title_color') ? 'style="color:'.$section->get_property('title_color').';"' : ''; 400 | 401 | $title_html .= '<'.$title_type.' class="'.$title_class.'" '.$title_style.'>'; 402 | $title_html .= THWEPO_i18n::esc_html__t($section->get_property('title')); 403 | $title_html .= ''; 404 | } 405 | 406 | $subtitle_html = ''; 407 | if($section->get_property('subtitle')){ 408 | $subtitle_class = THWEPO_Utils::convert_cssclass_string($section->get_property('subtitle_class')); 409 | $subtitle_type = $section->get_property('subtitle_type') ? $section->get_property('subtitle_type') : 'span'; 410 | $subtitle_style = $section->get_property('subtitle_color') ? 'color:'.$section->get_property('subtitle_color').';' : ''; 411 | $subtitle_style = 'style="font-size:80%; '.$subtitle_style.'"'; 412 | 413 | $subtitle_html .= !empty($title_html) ? '
    ' : ''; 414 | $subtitle_html .= '<'.$subtitle_type.' class="'.$subtitle_class.'" '.$subtitle_style.'>'; 415 | $subtitle_html .= THWEPO_i18n::esc_html__t($section->get_property('subtitle')); 416 | $subtitle_html .= ''; 417 | } 418 | 419 | $html = $title_html; 420 | if(!empty($subtitle_html)){ 421 | $html .= $subtitle_html; 422 | } 423 | 424 | if(!empty($html)){ 425 | $html = ''.$html.''; 426 | }else{ 427 | $html = ' '; 428 | } 429 | return $html; 430 | } 431 | 432 | private static function get_ajax_conditions_data($section){ 433 | $data_str = false; 434 | if($section->get_property('conditional_rules_ajax_json')){ 435 | $rules_action = $section->get_property('rules_action_ajax') ? $section->get_property('rules_action_ajax') : 'show'; 436 | $rules = urldecode($section->get_property('conditional_rules_ajax_json')); 437 | $rules = esc_js($rules); 438 | 439 | $data_str = 'id="'.$section->name.'" data-rules="'. $rules .'" data-rules-action="'. $rules_action .'" data-rules-elm="section"'; 440 | } 441 | return $data_str; 442 | } 443 | } 444 | 445 | endif; -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | \n" 13 | "Language-Team: LANGUAGE \n" 14 | 15 | msgid "WooCommerce Extra Product Options" 16 | msgstr "" 17 | 18 | msgid "WooCommerce Extra Product Options Pro" 19 | msgstr "" 20 | 21 | msgid "Documentation" 22 | msgstr "" 23 | 24 | msgid "Dismiss" 25 | msgstr "" 26 | 27 | msgid "Design woocommerce Product form in your own way, customize Product fields(Add, Edit, Delete and re arrange fields)." 28 | msgstr "" 29 | 30 | msgid "Extra Product Option" 31 | msgstr "" 32 | 33 | msgid "Product Options" 34 | msgstr "" 35 | 36 | msgid "Add new section" 37 | msgstr "" 38 | 39 | msgid "Delete Section" 40 | msgstr "" 41 | 42 | msgid "Edit Section" 43 | msgstr "" 44 | 45 | msgid "+ Add field" 46 | msgstr "" 47 | 48 | msgid "Remove" 49 | msgstr "" 50 | 51 | msgid "Enable" 52 | msgstr "" 53 | 54 | msgid "Disable" 55 | msgstr "" 56 | 57 | msgid "Save changes" 58 | msgstr "" 59 | 60 | msgid "Reset to default fields" 61 | msgstr "" 62 | 63 | msgid "Your changes were not saved due to an error (or you made none!)." 64 | msgstr "" 65 | 66 | msgid "Your changes were not saved due to no fields found." 67 | msgstr "" 68 | 69 | msgid "Your changes were saved." 70 | msgstr "" 71 | 72 | msgid "Name" 73 | msgstr "" 74 | 75 | msgid "Type" 76 | msgstr "" 77 | 78 | msgid "Label" 79 | msgstr "" 80 | 81 | msgid "Placeholder" 82 | msgstr "" 83 | 84 | msgid "Validation Rules" 85 | msgstr "" 86 | 87 | msgid "Required" 88 | msgstr "" 89 | 90 | msgid "Enabled" 91 | msgstr "" 92 | 93 | msgid "Edit" 94 | msgstr "" 95 | 96 | msgid "Create New Section" 97 | msgstr "" 98 | 99 | msgid "New section added successfully." 100 | msgstr "" 101 | 102 | msgid "New section not added due to an error." 103 | msgstr "" 104 | 105 | msgid "Section details updated successfully." 106 | msgstr "" 107 | 108 | msgid "Section details not updated due to an error." 109 | msgstr "" 110 | 111 | msgid "Section removed successfully." 112 | msgstr "" 113 | 114 | msgid "Section not removed due to an error." 115 | msgstr "" 116 | 117 | msgid "Name/ID" 118 | msgstr "" 119 | 120 | msgid "Display Position" 121 | msgstr "" 122 | 123 | msgid "CSS Class" 124 | msgstr "" 125 | 126 | msgid "Show section title in product page." 127 | msgstr "" 128 | 129 | msgid "Title" 130 | msgstr "" 131 | 132 | msgid "Title Position" 133 | msgstr "" 134 | 135 | msgid "Title Type" 136 | msgstr "" 137 | 138 | msgid "Title Color" 139 | msgstr "" 140 | 141 | msgid "Title Class" 142 | msgstr "" 143 | 144 | msgid "Subtitle" 145 | msgstr "" 146 | 147 | msgid "Subtitle Type" 148 | msgstr "" 149 | 150 | msgid "Subtitle Color" 151 | msgstr "" 152 | 153 | msgid "Subtitle Class" 154 | msgstr "" 155 | 156 | msgid "Add subtitle" 157 | msgstr "" 158 | 159 | msgid "Before Add To Cart Button" 160 | msgstr "" 161 | 162 | msgid "After Add To Cart Button" 163 | msgstr "" 164 | 165 | msgid "New Product Field" 166 | msgstr "" 167 | 168 | msgid "General Properties" 169 | msgstr "" 170 | 171 | msgid "Conditional Rules" 172 | msgstr "" 173 | 174 | msgid "Field Type" 175 | msgstr "" 176 | 177 | msgid "Default Value" 178 | msgstr "" 179 | 180 | msgid "Validation" 181 | msgstr "" 182 | 183 | msgid "Price" 184 | msgstr "" 185 | 186 | msgid "Unit" 187 | msgstr "" 188 | 189 | msgid "Price Type" 190 | msgstr "" 191 | 192 | msgid "Min. Length" 193 | msgstr "" 194 | 195 | msgid "Max. Length" 196 | msgstr "" 197 | 198 | msgid "Default Date" 199 | msgstr "" 200 | 201 | msgid "Date Format" 202 | msgstr "" 203 | 204 | msgid "Min. Date" 205 | msgstr "" 206 | 207 | msgid "Max. Date" 208 | msgstr "" 209 | 210 | msgid "Year Range" 211 | msgstr "" 212 | 213 | msgid "Number Of Months" 214 | msgstr "" 215 | 216 | msgid "Disabled Days" 217 | msgstr "" 218 | 219 | msgid "Disabled Dates" 220 | msgstr "" 221 | 222 | msgid "Leave empty for today's date" 223 | msgstr "" 224 | 225 | msgid "The minimum selectable date" 226 | msgstr "" 227 | 228 | msgid "The maximum selectable date" 229 | msgstr "" 230 | 231 | msgid "Select days to disable" 232 | msgstr "" 233 | 234 | msgid "Seperate dates with comma" 235 | msgstr "" 236 | 237 | msgid "Min. Time" 238 | msgstr "" 239 | 240 | msgid "Max. Time" 241 | msgstr "" 242 | 243 | msgid "Time Step" 244 | msgstr "" 245 | 246 | msgid "Time Format" 247 | msgstr "" 248 | 249 | msgid "Specify a date in the current dateFormat, or number of days from today (e.g. +7) or a string of values and periods ('y' for years, 'm' for months, 'w' for weeks, 'd' for days, e.g. '+1m +7d'), or leave empty for today." 250 | msgstr "" 251 | 252 | msgid "The format for parsed and displayed dates." 253 | msgstr "" 254 | 255 | msgid "The minimum selectable date. Specify a date in the current dateFormat, or number of days from today (e.g. -7) or a string of values and periods ('y' for years, 'm' for months, 'w' for weeks, 'd' for days, e.g. '-1m -7d'), or leave empty for no minimum limit." 256 | msgstr "" 257 | 258 | msgid "The maximum selectable date. Specify a date in the current dateFormat, or number of days from today (e.g. +7) or a string of values and periods ('y' for years, 'm' for months, 'w' for weeks, 'd' for days, e.g. '+1m +7d'), or leave empty for no maximum limit." 259 | msgstr "" 260 | 261 | msgid "The range of years displayed in the year drop-down: either relative to today's year ('-nn:+nn' e.g. -5:+3), relative to the currently selected year ('c-nn:c+nn' e.g. c-10:c+10), absolute ('nnnn:nnnn' e.g. 2002:2012), or combinations of these formats ('nnnn:+nn' e.g. 2002:+3). Note that this option only affects what appears in the drop-down, to restrict which dates may be selected use the minDate and/or maxDate options." 262 | msgstr "" 263 | 264 | msgid "The number of months to show at once" 265 | msgstr "" 266 | 267 | msgid "Specify dates in yyyy-mm-dd format separated by comma." 268 | msgstr "" 269 | 270 | msgid "Show" 271 | msgstr "" 272 | 273 | msgid "Hide" 274 | msgstr "" 275 | 276 | msgid "field if all below conditions are met." 277 | msgstr "" 278 | 279 | msgid "Product" 280 | msgstr "" 281 | 282 | msgid "Category" 283 | msgstr "" 284 | 285 | msgid "Equals to/ In" 286 | msgstr "" 287 | 288 | msgid "Not Equals to/ Not in" 289 | msgstr "" 290 | 291 | msgid "AND" 292 | msgstr "" 293 | 294 | msgid "OR" 295 | msgstr "" 296 | 297 | msgid "(%s) is not a valid number." 298 | msgstr "" 299 | 300 | msgid "(%s) is not a valid email address." 301 | msgstr "" 302 | 303 | msgid "Please enter a value for %s" 304 | msgstr "" -------------------------------------------------------------------------------- /public/assets/css/thwepo-public.min.css: -------------------------------------------------------------------------------- 1 | .woocommerce div.product form.cart table.extra-options,table.extra-options{width:100%}.single-product div.product table.extra-options th,table.extra-options td{background-color:transparent}.single-product div.product table.extra-options th.leftside,table.extra-options td.leftside{display:table-cell}.single-product div.product table.extra-options th.above,table.extra-options td.above{display:list-item;padding:0;list-style:none}table.extra-options .label-tag,table.extra-options .sublabel-tag{display:inline-block}table.extra-options .required{border-bottom:0!important;color:red;text-decoration:none}table.extra-options select{min-width:80px}table.extra-options input[type=checkbox]{vertical-align:top;margin-top:5px}table.extra-options .label-wrapper-checkbox{padding:0;margin:0;display:inline-block}.font-size-80-perc{font-size:80%!important}.font-size-100-perc{font-size:100%!important}.display-table-cell{display:table-cell!important}.display-list-item{display:list-item!important}.label-field-cell{display:table-cell!important}.no-border,.no-border td{border:0!important}.strong{font-weight:700!important}.cell-p-0 td,.cell-p-0 th,.p-0{padding:0!important}.cell-p-5 td,.cell-p-5 th,.p-5{padding:5!important}.cell-p-10 td,.cell-p-10 th,.p-10{padding:10!important}.ui-widget-content{z-index:99999!important}.ui-datepicker .ui-datepicker-title select{color:initial;padding-right:0;display:inline-block;height:auto}.ui-datepicker .ui-datepicker-buttonpane button{text-transform:capitalize;letter-spacing:normal;line-height:initial;min-height:0}.select2-results .select2-results__option{white-space:nowrap}.select2-container{z-index:99999}.iris-picker{z-index:100;display:none;position:absolute!important;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.2)}.iris-picker .ui-slider{border:0!important;margin:0!important;width:auto!important;height:auto!important;background:0 0!important}.iris-picker .ui-slider .ui-slider-handle{margin-bottom:0!important}.thwepo-colorpicker-preview{padding:10px 22px 12px;border:1px solid rgba(0,0,0,.125);background-color:#FFF}.thwepo-color-picker{border-left:0}.thwepo-colorpicker-preview.thplwepo-round{border-radius:50%;margin-right:12px}.thwepo_tooltip{font-size:inherit;color:#fff;--tooltip-bg:#333;display:inline-block;vertical-align:middle;position:relative;height:100%;margin-left:3px;z-index:999999}.thwepo_tooltip img{padding:0;vertical-align:middle;cursor:help;border:none;height:16px;width:16px}.thwepo_tooltip:hover:after{font-size:inherit;color:inherit;background:#333;background:rgba(0,0,0,1);border-radius:5px;bottom:26px;content:attr(title);left:-100px;padding:10px 15px;position:absolute;z-index:9998;width:350px;background-color:var(--tooltip-bg)}.thwepo_tooltip:hover:before{border:solid;border-color:#000 transparent;border-color:var(--tooltip-bg) transparent;border-width:6px 6px 0;bottom:20px;content:"";left:50%;position:absolute;z-index:9999} -------------------------------------------------------------------------------- /public/assets/js/timepicker/jquery.timepicker.css: -------------------------------------------------------------------------------- 1 | .ui-timepicker-wrapper { 2 | overflow-y: auto; 3 | height: 150px; 4 | width: 6.5em; 5 | background: #fff; 6 | border: 1px solid #ddd; 7 | -webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2); 8 | -moz-box-shadow:0 5px 10px rgba(0,0,0,0.2); 9 | box-shadow:0 5px 10px rgba(0,0,0,0.2); 10 | outline: none; 11 | z-index: 10001; 12 | margin: 0; 13 | } 14 | 15 | .ui-timepicker-wrapper.ui-timepicker-with-duration { 16 | width: 13em; 17 | } 18 | 19 | .ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30, 20 | .ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60 { 21 | width: 11em; 22 | } 23 | 24 | .ui-timepicker-list { 25 | margin: 0; 26 | padding: 0; 27 | list-style: none; 28 | } 29 | 30 | .ui-timepicker-duration { 31 | margin-left: 5px; color: #888; 32 | } 33 | 34 | .ui-timepicker-list:hover .ui-timepicker-duration { 35 | color: #888; 36 | } 37 | 38 | .ui-timepicker-list li { 39 | padding: 3px 0 3px 5px; 40 | cursor: pointer; 41 | white-space: nowrap; 42 | color: #000; 43 | list-style: none; 44 | margin: 0; 45 | } 46 | 47 | .ui-timepicker-list:hover .ui-timepicker-selected { 48 | background: #fff; color: #000; 49 | } 50 | 51 | li.ui-timepicker-selected, 52 | .ui-timepicker-list li:hover, 53 | .ui-timepicker-list .ui-timepicker-selected:hover { 54 | background: #1980EC; color: #fff; 55 | } 56 | 57 | li.ui-timepicker-selected .ui-timepicker-duration, 58 | .ui-timepicker-list li:hover .ui-timepicker-duration { 59 | color: #ccc; 60 | } 61 | 62 | .ui-timepicker-list li.ui-timepicker-disabled, 63 | .ui-timepicker-list li.ui-timepicker-disabled:hover, 64 | .ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled { 65 | color: #888; 66 | cursor: default; 67 | } 68 | 69 | .ui-timepicker-list li.ui-timepicker-disabled:hover, 70 | .ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled { 71 | background: #f2f2f2; 72 | } 73 | -------------------------------------------------------------------------------- /public/assets/js/timepicker/jquery.timepicker.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jquery-timepicker v1.8.5 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation. 3 | * Copyright (c) 2015 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/ 4 | * License: MIT 5 | */ 6 | 7 | !function(a){"object"==typeof exports&&exports&&"object"==typeof module&&module&&module.exports===exports?a(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){var b=a[0];return b.offsetWidth>0&&b.offsetHeight>0}function c(b){if(b.minTime&&(b.minTime=u(b.minTime)),b.maxTime&&(b.maxTime=u(b.maxTime)),b.durationTime&&"function"!=typeof b.durationTime&&(b.durationTime=u(b.durationTime)),"now"==b.scrollDefault)b.scrollDefault=function(){return b.roundingFunction(u(new Date),b)};else if(b.scrollDefault&&"function"!=typeof b.scrollDefault){var c=b.scrollDefault;b.scrollDefault=function(){return b.roundingFunction(u(c),b)}}else b.minTime&&(b.scrollDefault=function(){return b.roundingFunction(b.minTime,b)});if("string"===a.type(b.timeFormat)&&b.timeFormat.match(/[gh]/)&&(b._twelveHourTime=!0),b.showOnFocus===!1&&-1!=b.showOn.indexOf("focus")&&b.showOn.splice(b.showOn.indexOf("focus"),1),b.disableTimeRanges.length>0){for(var d in b.disableTimeRanges)b.disableTimeRanges[d]=[u(b.disableTimeRanges[d][0]),u(b.disableTimeRanges[d][1])];b.disableTimeRanges=b.disableTimeRanges.sort(function(a,b){return a[0]-b[0]});for(var d=b.disableTimeRanges.length-1;d>0;d--)b.disableTimeRanges[d][0]<=b.disableTimeRanges[d-1][1]&&(b.disableTimeRanges[d-1]=[Math.min(b.disableTimeRanges[d][0],b.disableTimeRanges[d-1][0]),Math.max(b.disableTimeRanges[d][1],b.disableTimeRanges[d-1][1])],b.disableTimeRanges.splice(d,1))}return b}function d(b){var c=b.data("timepicker-settings"),d=b.data("timepicker-list");if(d&&d.length&&(d.remove(),b.data("timepicker-list",!1)),c.useSelect){d=a("