| 1 |
<?php |
| 2 |
|
| 3 |
namespace TierPricingTable\Addons\GlobalTieredPricing; |
| 4 |
|
| 5 |
use TierPricingTable\Addons\GlobalTieredPricing\PricingRule\RuleSettings; |
| 6 |
use TierPricingTable\Forms\Form; |
| 7 |
use Exception; |
| 8 |
use WC_Product; |
| 9 |
use WP_User; |
| 10 |
class GlobalPricingRule { |
| 11 |
/** |
| 12 |
* Rule ID |
| 13 |
* |
| 14 |
* @var int |
| 15 |
*/ |
| 16 |
public $id; |
| 17 |
|
| 18 |
/** |
| 19 |
* Is suspended |
| 20 |
* |
| 21 |
* @var bool |
| 22 |
*/ |
| 23 |
public $isSuspended = false; |
| 24 |
|
| 25 |
/** |
| 26 |
* Regular pricing type |
| 27 |
* |
| 28 |
* @var string |
| 29 |
*/ |
| 30 |
public $pricingType; |
| 31 |
|
| 32 |
/** |
| 33 |
* Regular price |
| 34 |
* |
| 35 |
* @var ?float |
| 36 |
*/ |
| 37 |
public $regularPrice; |
| 38 |
|
| 39 |
/** |
| 40 |
* Sale price |
| 41 |
* |
| 42 |
* @var ?float |
| 43 |
*/ |
| 44 |
public $salePrice; |
| 45 |
|
| 46 |
/** |
| 47 |
* Percentage Discount |
| 48 |
* |
| 49 |
* @var ?float |
| 50 |
*/ |
| 51 |
public $discount; |
| 52 |
|
| 53 |
/** |
| 54 |
* Percentage Discount |
| 55 |
* |
| 56 |
* @var string |
| 57 |
*/ |
| 58 |
public $discountType = 'sale_price'; |
| 59 |
|
| 60 |
/** |
| 61 |
* Applying type |
| 62 |
* |
| 63 |
* @var string |
| 64 |
*/ |
| 65 |
public $applyingType; |
| 66 |
|
| 67 |
/** |
| 68 |
* Tax status |
| 69 |
* |
| 70 |
* @var string |
| 71 |
*/ |
| 72 |
public $taxStatus = ''; |
| 73 |
|
| 74 |
/** |
| 75 |
* Tax class |
| 76 |
* |
| 77 |
* @var string |
| 78 |
*/ |
| 79 |
public $taxClass = ''; |
| 80 |
|
| 81 |
/** |
| 82 |
* Tiered Pricing type |
| 83 |
* |
| 84 |
* @var string |
| 85 |
*/ |
| 86 |
public $tieredPricingType; |
| 87 |
|
| 88 |
/** |
| 89 |
* Percentage Tiered Pricing Rules |
| 90 |
* |
| 91 |
* @var array |
| 92 |
*/ |
| 93 |
public $percentageTieredPricingRules = array(); |
| 94 |
|
| 95 |
/** |
| 96 |
* Fixed Tiered Pricing Rules |
| 97 |
* |
| 98 |
* @var array |
| 99 |
*/ |
| 100 |
public $fixedTieredPricingRules = array(); |
| 101 |
|
| 102 |
/** |
| 103 |
* Included categories |
| 104 |
* |
| 105 |
* @var array |
| 106 |
*/ |
| 107 |
public $includedProductCategories = array(); |
| 108 |
|
| 109 |
/** |
| 110 |
* Excluded categories |
| 111 |
* |
| 112 |
* @var array |
| 113 |
*/ |
| 114 |
public $excludedProductCategories = array(); |
| 115 |
|
| 116 |
/** |
| 117 |
* Included tags |
| 118 |
* |
| 119 |
* @var array |
| 120 |
*/ |
| 121 |
public $includedProductTags = array(); |
| 122 |
|
| 123 |
/** |
| 124 |
* Excluded tags |
| 125 |
* |
| 126 |
* @var array |
| 127 |
*/ |
| 128 |
public $excludedProductTags = array(); |
| 129 |
|
| 130 |
/** |
| 131 |
* Included brands |
| 132 |
* |
| 133 |
* @var array |
| 134 |
*/ |
| 135 |
public $includedProductBrands = array(); |
| 136 |
|
| 137 |
/** |
| 138 |
* Excluded brands |
| 139 |
* |
| 140 |
* @var array |
| 141 |
*/ |
| 142 |
public $excludedProductBrands = array(); |
| 143 |
|
| 144 |
/** |
| 145 |
* Included products |
| 146 |
* |
| 147 |
* @var array |
| 148 |
*/ |
| 149 |
public $includedProducts = array(); |
| 150 |
|
| 151 |
/** |
| 152 |
* Excluded products |
| 153 |
* |
| 154 |
* @var array |
| 155 |
*/ |
| 156 |
public $excludedProducts = array(); |
| 157 |
|
| 158 |
/** |
| 159 |
* Included product roles |
| 160 |
* |
| 161 |
* @var array |
| 162 |
*/ |
| 163 |
public $includedUsersRole = array(); |
| 164 |
|
| 165 |
/** |
| 166 |
* Excluded product roles |
| 167 |
* |
| 168 |
* @var array |
| 169 |
*/ |
| 170 |
public $excludedUsersRole = array(); |
| 171 |
|
| 172 |
/** |
| 173 |
* Included users |
| 174 |
* |
| 175 |
* @var array |
| 176 |
*/ |
| 177 |
public $includedUsers = array(); |
| 178 |
|
| 179 |
/** |
| 180 |
* Excluded users |
| 181 |
* |
| 182 |
* @var array |
| 183 |
*/ |
| 184 |
public $excludedUsers = array(); |
| 185 |
|
| 186 |
/** |
| 187 |
* Product minimum purchase quantity |
| 188 |
* |
| 189 |
* @var int |
| 190 |
*/ |
| 191 |
public $minimum; |
| 192 |
|
| 193 |
public $priorityOptions; |
| 194 |
|
| 195 |
/** |
| 196 |
* Array with custom data from 3rd-party addons |
| 197 |
* |
| 198 |
* @var array |
| 199 |
*/ |
| 200 |
public $data = array(); |
| 201 |
|
| 202 |
public function getId() : int { |
| 203 |
return $this->id; |
| 204 |
} |
| 205 |
|
| 206 |
public function setId( int $id ) { |
| 207 |
$this->id = $id; |
| 208 |
} |
| 209 |
|
| 210 |
public function getDiscount() : ?float { |
| 211 |
return $this->discount; |
| 212 |
} |
| 213 |
|
| 214 |
public function setDiscount( ?float $discount ) { |
| 215 |
$this->discount = $discount; |
| 216 |
} |
| 217 |
|
| 218 |
public function getDiscountType() : string { |
| 219 |
return $this->discountType; |
| 220 |
} |
| 221 |
|
| 222 |
public function setDiscountType( string $discountType ) { |
| 223 |
$this->discountType = ( in_array( $discountType, array('sale_price', 'regular_price') ) ? $discountType : 'sale_price' ); |
| 224 |
} |
| 225 |
|
| 226 |
public function getTieredPricingType() : string { |
| 227 |
return 'fixed'; |
| 228 |
} |
| 229 |
|
| 230 |
public function setTieredPricingType( string $tieredPricingType ) { |
| 231 |
$this->tieredPricingType = ( in_array( $tieredPricingType, array('percentage', 'fixed') ) ? $tieredPricingType : 'fixed' ); |
| 232 |
} |
| 233 |
|
| 234 |
public function getPercentageTieredPricingRules() : array { |
| 235 |
return $this->percentageTieredPricingRules; |
| 236 |
} |
| 237 |
|
| 238 |
public function setPercentageTieredPricingRules( array $percentageTieredPricingRules ) { |
| 239 |
$this->percentageTieredPricingRules = $percentageTieredPricingRules; |
| 240 |
} |
| 241 |
|
| 242 |
public function getFixedTieredPricingRules() : array { |
| 243 |
return $this->fixedTieredPricingRules; |
| 244 |
} |
| 245 |
|
| 246 |
public function setFixedTieredPricingRules( array $fixedTieredPricingRules ) { |
| 247 |
$this->fixedTieredPricingRules = $fixedTieredPricingRules; |
| 248 |
} |
| 249 |
|
| 250 |
public function getApplyingType() : string { |
| 251 |
return $this->applyingType; |
| 252 |
} |
| 253 |
|
| 254 |
public function setApplyingType( string $applyingType ) { |
| 255 |
$this->applyingType = ( in_array( $applyingType, array('individual', 'cross') ) ? $applyingType : 'cross' ); |
| 256 |
} |
| 257 |
|
| 258 |
public function getPricingType() : string { |
| 259 |
return $this->pricingType; |
| 260 |
} |
| 261 |
|
| 262 |
public function setPricingType( string $priceType ) { |
| 263 |
$this->pricingType = ( in_array( $priceType, array('percentage', 'flat') ) ? $priceType : 'flat' ); |
| 264 |
} |
| 265 |
|
| 266 |
public function getTieredPricingRules() : array { |
| 267 |
return $this->getFixedTieredPricingRules(); |
| 268 |
} |
| 269 |
|
| 270 |
public function getTaxStatus() : string { |
| 271 |
return $this->taxStatus; |
| 272 |
} |
| 273 |
|
| 274 |
public function setTaxStatus( string $taxStatus ) { |
| 275 |
$this->taxStatus = $taxStatus; |
| 276 |
} |
| 277 |
|
| 278 |
public function getTaxClass() : string { |
| 279 |
return $this->taxClass; |
| 280 |
} |
| 281 |
|
| 282 |
public function setTaxClass( string $taxClass ) { |
| 283 |
$this->taxClass = $taxClass; |
| 284 |
} |
| 285 |
|
| 286 |
public function getRegularPrice() : ?float { |
| 287 |
return $this->regularPrice; |
| 288 |
} |
| 289 |
|
| 290 |
public function setRegularPrice( ?float $regularPrice ) { |
| 291 |
$this->regularPrice = ( !Form::isEmpty( $regularPrice ) ? floatval( $regularPrice ) : null ); |
| 292 |
} |
| 293 |
|
| 294 |
public function getSalePrice() : ?float { |
| 295 |
return $this->salePrice; |
| 296 |
} |
| 297 |
|
| 298 |
public function setSalePrice( ?float $salePrice ) { |
| 299 |
$this->salePrice = $salePrice; |
| 300 |
} |
| 301 |
|
| 302 |
/** |
| 303 |
* Create instance from array |
| 304 |
* |
| 305 |
* @param array $data |
| 306 |
* |
| 307 |
* @return self |
| 308 |
*/ |
| 309 |
public static function fromArray( array $data ) : self { |
| 310 |
$applyingType = $data['applying_type'] ?? 'individual'; |
| 311 |
$applyingType = ( in_array( $applyingType, array('individual', 'cross') ) ? $applyingType : 'cross' ); |
| 312 |
$tieredPricingType = $data['tiered_pricing_type'] ?? 'fixed'; |
| 313 |
$tieredPricingType = ( in_array( $tieredPricingType, array('flat', 'percentage') ) ? $tieredPricingType : 'fixed' ); |
| 314 |
$percentageRules = ( isset( $data['percentage_rules'] ) ? (array) $data['percentage_rules'] : array() ); |
| 315 |
$fixedRules = ( isset( $data['fixed_rules'] ) ? (array) $data['fixed_rules'] : array() ); |
| 316 |
$pricingType = $data['pricing_type'] ?? 'flat'; |
| 317 |
$pricingType = ( in_array( $pricingType, array('flat', 'percentage') ) ? $pricingType : 'flat' ); |
| 318 |
$regularPrice = $data['regular_price'] ?? null; |
| 319 |
$salePrice = $data['sale_price'] ?? null; |
| 320 |
$discount = $data['discount'] ?? null; |
| 321 |
$discountType = $data['discount_type'] ?? 'sale_price'; |
| 322 |
$minimum = $data['minimum'] ?? null; |
| 323 |
$taxStatus = $data['tax_status'] ?? ''; |
| 324 |
$taxClass = $data['tax_class'] ?? ''; |
| 325 |
$self = new self(); |
| 326 |
$self->setTaxStatus( $taxStatus ); |
| 327 |
$self->setTaxClass( $taxClass ); |
| 328 |
$self->setPricingType( (string) $pricingType ); |
| 329 |
$self->setRegularPrice( ( Form::isEmpty( $regularPrice ) ? null : (float) $regularPrice ) ); |
| 330 |
$self->setSalePrice( ( Form::isEmpty( $salePrice ) ? null : (float) $salePrice ) ); |
| 331 |
$self->setDiscount( ( Form::isEmpty( $discount ) ? null : (float) $discount ) ); |
| 332 |
$self->setDiscountType( (string) $discountType ); |
| 333 |
$self->setApplyingType( $applyingType ); |
| 334 |
$self->setTieredPricingType( $tieredPricingType ); |
| 335 |
$self->setPercentageTieredPricingRules( $percentageRules ); |
| 336 |
$self->setFixedTieredPricingRules( $fixedRules ); |
| 337 |
$self->setMinimum( ( Form::isEmpty( $minimum ) ? null : (int) $minimum ) ); |
| 338 |
return $self; |
| 339 |
} |
| 340 |
|
| 341 |
/** |
| 342 |
* Validate |
| 343 |
* |
| 344 |
* @throws Exception |
| 345 |
*/ |
| 346 |
public function validatePricing() { |
| 347 |
$valid = !Form::isEmpty( $this->getRegularPrice() ); |
| 348 |
$valid = $valid || !Form::isEmpty( $this->getSalePrice() ); |
| 349 |
$valid = $valid || !empty( $this->getTieredPricingRules() ); |
| 350 |
$valid = $valid || !Form::isEmpty( $this->getMinimum() ); |
| 351 |
$valid = $valid || !Form::isEmpty( $this->getDiscount() ); |
| 352 |
$valid = $valid || $this->getSettings()->getPriorityType() === 'flexible'; |
| 353 |
$valid = apply_filters( 'tiered_pricing_table/global_pricing/validation', $valid, $this ); |
| 354 |
if ( !$valid ) { |
| 355 |
throw new Exception(esc_html__( 'The pricing rule does not affect either prices or product quantity. The rule will be skipped.', 'tier-pricing-table' )); |
| 356 |
} |
| 357 |
} |
| 358 |
|
| 359 |
public function isValidPricing() : bool { |
| 360 |
try { |
| 361 |
$this->validatePricing(); |
| 362 |
} catch ( Exception $e ) { |
| 363 |
return false; |
| 364 |
} |
| 365 |
return true; |
| 366 |
} |
| 367 |
|
| 368 |
public function getMinimum() : ?int { |
| 369 |
return $this->minimum; |
| 370 |
} |
| 371 |
|
| 372 |
public function setMinimum( ?int $minimum ) { |
| 373 |
$this->minimum = ( intval( $minimum ) > 1 ? $minimum : null ); |
| 374 |
} |
| 375 |
|
| 376 |
public function getIncludedProductCategories() : array { |
| 377 |
return $this->includedProductCategories; |
| 378 |
} |
| 379 |
|
| 380 |
public function getExcludedProductCategories() : array { |
| 381 |
return $this->excludedProductCategories; |
| 382 |
} |
| 383 |
|
| 384 |
public function setIncludedProductCategories( array $includedProductCategories ) { |
| 385 |
$this->includedProductCategories = $includedProductCategories; |
| 386 |
} |
| 387 |
|
| 388 |
public function setExcludedProductCategories( array $excludedProductCategories ) { |
| 389 |
$this->excludedProductCategories = $excludedProductCategories; |
| 390 |
} |
| 391 |
|
| 392 |
public function getIncludedProductTags() : array { |
| 393 |
return $this->includedProductTags; |
| 394 |
} |
| 395 |
|
| 396 |
public function getExcludedProductTags() : array { |
| 397 |
return $this->excludedProductTags; |
| 398 |
} |
| 399 |
|
| 400 |
public function setIncludedProductTags( array $includedProductTags ) { |
| 401 |
$this->includedProductTags = $includedProductTags; |
| 402 |
} |
| 403 |
|
| 404 |
public function setExcludedProductTags( array $excludedProductTags ) { |
| 405 |
$this->excludedProductTags = $excludedProductTags; |
| 406 |
} |
| 407 |
|
| 408 |
public function getIncludedProductBrands() : array { |
| 409 |
return $this->includedProductBrands; |
| 410 |
} |
| 411 |
|
| 412 |
public function getExcludedProductBrands() : array { |
| 413 |
return $this->excludedProductBrands; |
| 414 |
} |
| 415 |
|
| 416 |
public function setIncludedProductBrands( array $includedProductBrands ) { |
| 417 |
$this->includedProductBrands = $includedProductBrands; |
| 418 |
} |
| 419 |
|
| 420 |
public function setExcludedProductBrands( array $excludedProductBrands ) { |
| 421 |
$this->excludedProductBrands = $excludedProductBrands; |
| 422 |
} |
| 423 |
|
| 424 |
public function getIncludedProducts() : array { |
| 425 |
return $this->includedProducts; |
| 426 |
} |
| 427 |
|
| 428 |
public function getExcludedProducts() : array { |
| 429 |
return $this->excludedProducts; |
| 430 |
} |
| 431 |
|
| 432 |
public function setIncludedProducts( array $includedProducts ) { |
| 433 |
$this->includedProducts = $includedProducts; |
| 434 |
} |
| 435 |
|
| 436 |
public function setExcludedProducts( array $excludedProducts ) { |
| 437 |
$this->excludedProducts = $excludedProducts; |
| 438 |
} |
| 439 |
|
| 440 |
public function getIncludedUserRoles() : array { |
| 441 |
return $this->includedUsersRole; |
| 442 |
} |
| 443 |
|
| 444 |
public function getExcludedUserRoles() : array { |
| 445 |
return $this->excludedUsersRole; |
| 446 |
} |
| 447 |
|
| 448 |
public function setIncludedUsersRole( array $includedUsersRole ) { |
| 449 |
$this->includedUsersRole = $includedUsersRole; |
| 450 |
} |
| 451 |
|
| 452 |
public function setExcludedUsersRole( array $excludedUsersRole ) { |
| 453 |
$this->excludedUsersRole = $excludedUsersRole; |
| 454 |
} |
| 455 |
|
| 456 |
public function getIncludedUsers() : array { |
| 457 |
return $this->includedUsers; |
| 458 |
} |
| 459 |
|
| 460 |
public function getExcludedUsers() : array { |
| 461 |
return $this->excludedUsers; |
| 462 |
} |
| 463 |
|
| 464 |
public function setIncludedUsers( array $includedUsers ) { |
| 465 |
$this->includedUsers = $includedUsers; |
| 466 |
} |
| 467 |
|
| 468 |
public function setExcludedUsers( array $excludedUsers ) { |
| 469 |
$this->excludedUsers = $excludedUsers; |
| 470 |
} |
| 471 |
|
| 472 |
public function getSettings() : RuleSettings { |
| 473 |
if ( !$this->priorityOptions ) { |
| 474 |
$this->priorityOptions = new RuleSettings($this); |
| 475 |
} |
| 476 |
return $this->priorityOptions; |
| 477 |
} |
| 478 |
|
| 479 |
public function asArray() : array { |
| 480 |
return array( |
| 481 |
'pricing_type' => $this->getPricingType(), |
| 482 |
'regular_price' => $this->getRegularPrice(), |
| 483 |
'sale_price' => $this->getSalePrice(), |
| 484 |
'discount' => $this->getDiscount(), |
| 485 |
'discount_type' => $this->getDiscountType(), |
| 486 |
'applying_type' => $this->getApplyingType(), |
| 487 |
'tiered_pricing_type' => $this->getTieredPricingType(), |
| 488 |
'percentage_rules' => $this->getPercentageTieredPricingRules(), |
| 489 |
'fixed_rules' => $this->getFixedTieredPricingRules(), |
| 490 |
'minimum' => $this->getMinimum(), |
| 491 |
'tax_status' => $this->getTaxStatus(), |
| 492 |
'tax_class' => $this->getTaxClass(), |
| 493 |
'included_categories' => $this->getIncludedProductCategories(), |
| 494 |
'included_tags' => $this->getIncludedProductTags(), |
| 495 |
'included_brands' => $this->getIncludedProductBrands(), |
| 496 |
'included_products' => $this->getIncludedProducts(), |
| 497 |
'included_users' => $this->getIncludedUsers(), |
| 498 |
'included_users_role' => $this->getIncludedUserRoles(), |
| 499 |
'excluded_categories' => $this->getExcludedProductCategories(), |
| 500 |
'excluded_tags' => $this->getExcludedProductTags(), |
| 501 |
'excluded_brands' => $this->getExcludedProductBrands(), |
| 502 |
'excluded_products' => $this->getExcludedProducts(), |
| 503 |
'excluded_users' => $this->getExcludedUsers(), |
| 504 |
'excluded_users_role' => $this->getExcludedUserRoles(), |
| 505 |
'rule_id' => $this->getId(), |
| 506 |
'is_suspended' => $this->isSuspended(), |
| 507 |
); |
| 508 |
} |
| 509 |
|
| 510 |
public function save() { |
| 511 |
$dataToUpdate = array( |
| 512 |
'_tpt_pricing_type' => $this->getPricingType(), |
| 513 |
'_tpt_regular_price' => $this->getRegularPrice(), |
| 514 |
'_tpt_sale_price' => $this->getSalePrice(), |
| 515 |
'_tpt_discount' => $this->getDiscount(), |
| 516 |
'_tpt_discount_type' => $this->getDiscountType(), |
| 517 |
'_tpt_applying_type' => $this->getApplyingType(), |
| 518 |
'_tpt_tiered_pricing_type' => $this->getTieredPricingType(), |
| 519 |
'_tpt_percentage_rules' => $this->getPercentageTieredPricingRules(), |
| 520 |
'_tpt_fixed_rules' => $this->getFixedTieredPricingRules(), |
| 521 |
'_tpt_minimum' => $this->getMinimum(), |
| 522 |
'_tpt_tax_status' => $this->getTaxStatus(), |
| 523 |
'_tpt_tax_class' => $this->getTaxClass(), |
| 524 |
'_tpt_included_categories' => $this->getIncludedProductCategories(), |
| 525 |
'_tpt_included_tags' => $this->getIncludedProductTags(), |
| 526 |
'_tpt_included_brands' => $this->getIncludedProductBrands(), |
| 527 |
'_tpt_included_products' => $this->getIncludedProducts(), |
| 528 |
'_tpt_included_users' => $this->getIncludedUsers(), |
| 529 |
'_tpt_included_user_roles' => $this->getIncludedUserRoles(), |
| 530 |
'_tpt_excluded_categories' => $this->getExcludedProductCategories(), |
| 531 |
'_tpt_excluded_tags' => $this->getExcludedProductTags(), |
| 532 |
'_tpt_excluded_brands' => $this->getExcludedProductBrands(), |
| 533 |
'_tpt_excluded_products' => $this->getExcludedProducts(), |
| 534 |
'_tpt_excluded_users' => $this->getExcludedUsers(), |
| 535 |
'_tpt_excluded_user_roles' => $this->getExcludedUserRoles(), |
| 536 |
'_tpt_is_suspended' => wc_bool_to_string( $this->isSuspended() ), |
| 537 |
); |
| 538 |
foreach ( $dataToUpdate as $key => $value ) { |
| 539 |
update_post_meta( $this->getId(), $key, $value ); |
| 540 |
} |
| 541 |
} |
| 542 |
|
| 543 |
public static function build( $ruleId ) : self { |
| 544 |
// Simple data to read |
| 545 |
$dataToRead = array( |
| 546 |
'_tpt_pricing_type' => 'pricing_type', |
| 547 |
'_tpt_sale_price' => 'sale_price', |
| 548 |
'_tpt_regular_price' => 'regular_price', |
| 549 |
'_tpt_discount' => 'discount', |
| 550 |
'_tpt_discount_type' => 'discount_type', |
| 551 |
'_tpt_applying_type' => 'applying_type', |
| 552 |
'_tpt_tiered_pricing_type' => 'tiered_pricing_type', |
| 553 |
'_tpt_minimum' => 'minimum', |
| 554 |
'_tpt_tax_status' => 'tax_status', |
| 555 |
'_tpt_tax_class' => 'tax_class', |
| 556 |
'_tpt_is_suspended' => 'is_suspended', |
| 557 |
); |
| 558 |
$data = array(); |
| 559 |
foreach ( $dataToRead as $key => $name ) { |
| 560 |
$data[$name] = get_post_meta( $ruleId, $key, true ); |
| 561 |
} |
| 562 |
$priceRule = self::fromArray( $data ); |
| 563 |
$existingRoles = wp_roles()->roles; |
| 564 |
$includedCategoriesIds = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_included_categories', true ) ) ); |
| 565 |
$includedTagsIds = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_included_tags', true ) ) ); |
| 566 |
$includedBrandsIds = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_included_brands', true ) ) ); |
| 567 |
$includedProductsIds = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_included_products', true ) ) ); |
| 568 |
$includedUsersRole = array_filter( (array) get_post_meta( $ruleId, '_tpt_included_user_roles', true ), function ( $role ) use($existingRoles) { |
| 569 |
return array_key_exists( $role, $existingRoles ); |
| 570 |
} ); |
| 571 |
$includedUsers = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_included_users', true ) ) ); |
| 572 |
$excludedCategoriesIds = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_excluded_categories', true ) ) ); |
| 573 |
$excludedTagsIds = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_excluded_tags', true ) ) ); |
| 574 |
$excludedBrandsIds = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_excluded_brands', true ) ) ); |
| 575 |
$excludedProductsIds = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_excluded_products', true ) ) ); |
| 576 |
$excludedUsersRole = array_filter( (array) get_post_meta( $ruleId, '_tpt_excluded_user_roles', true ), function ( $role ) use($existingRoles) { |
| 577 |
return array_key_exists( $role, $existingRoles ); |
| 578 |
} ); |
| 579 |
$excludedUsers = array_filter( array_map( 'intval', (array) get_post_meta( $ruleId, '_tpt_excluded_users', true ) ) ); |
| 580 |
$isSuspended = get_post_meta( $ruleId, '_tpt_is_suspended', true ) === 'yes'; |
| 581 |
$priceRule->setPercentageTieredPricingRules( self::readPricingRules( 'percentage', $ruleId ) ); |
| 582 |
$priceRule->setFixedTieredPricingRules( self::readPricingRules( 'fixed', $ruleId ) ); |
| 583 |
$priceRule->setIncludedProductCategories( $includedCategoriesIds ); |
| 584 |
$priceRule->setIncludedProductTags( $includedTagsIds ); |
| 585 |
$priceRule->setIncludedProductBrands( $includedBrandsIds ); |
| 586 |
$priceRule->setIncludedUsers( $includedUsers ); |
| 587 |
$priceRule->setIncludedUsersRole( $includedUsersRole ); |
| 588 |
$priceRule->setIncludedProducts( $includedProductsIds ); |
| 589 |
$priceRule->setExcludedProductCategories( $excludedCategoriesIds ); |
| 590 |
$priceRule->setExcludedProductTags( $excludedTagsIds ); |
| 591 |
$priceRule->setExcludedProductBrands( $excludedBrandsIds ); |
| 592 |
$priceRule->setExcludedUsers( $excludedUsers ); |
| 593 |
$priceRule->setExcludedUsersRole( $excludedUsersRole ); |
| 594 |
$priceRule->setExcludedProducts( $excludedProductsIds ); |
| 595 |
$priceRule->setIsSuspended( $isSuspended ); |
| 596 |
$priceRule->setId( $ruleId ); |
| 597 |
return apply_filters( 'tiered_pricing_table/global_pricing/after_built_rule', $priceRule ); |
| 598 |
} |
| 599 |
|
| 600 |
protected static function readPricingRules( $type, $id ) : array { |
| 601 |
$type = ( in_array( $type, array('percentage', 'fixed') ) ? $type : 'fixed' ); |
| 602 |
$rules = get_post_meta( $id, "_tpt_{$type}_rules", true ); |
| 603 |
$rules = ( !empty( $rules ) ? $rules : array() ); |
| 604 |
$rules = ( is_array( $rules ) ? array_filter( $rules ) : array() ); |
| 605 |
ksort( $rules ); |
| 606 |
return $rules; |
| 607 |
} |
| 608 |
|
| 609 |
public function setIsSuspended( bool $isSuspended ) { |
| 610 |
$this->isSuspended = $isSuspended; |
| 611 |
} |
| 612 |
|
| 613 |
public function suspend() { |
| 614 |
$this->setIsSuspended( true ); |
| 615 |
} |
| 616 |
|
| 617 |
public function reactivate() { |
| 618 |
$this->setIsSuspended( false ); |
| 619 |
} |
| 620 |
|
| 621 |
public function isSuspended() : bool { |
| 622 |
return $this->isSuspended; |
| 623 |
} |
| 624 |
|
| 625 |
/** |
| 626 |
* Wrapper for the main "match" function to provide the hook for 3rd party devs |
| 627 |
* |
| 628 |
* @param WP_User $user |
| 629 |
* @param WC_Product $product |
| 630 |
* |
| 631 |
* @return bool |
| 632 |
*/ |
| 633 |
public function matchRequirements( WP_User $user, WC_Product $product ) : bool { |
| 634 |
$matched = $this->_matchRequirements( $user, $product ); |
| 635 |
return apply_filters( |
| 636 |
'tiered_pricing_table/global_pricing/match_requirements', |
| 637 |
$matched, |
| 638 |
$this, |
| 639 |
$user, |
| 640 |
$product |
| 641 |
); |
| 642 |
} |
| 643 |
|
| 644 |
protected function _matchRequirements( WP_User $user, WC_Product $product ) : bool { |
| 645 |
$parentProduct = ( $product->is_type( array('variation', 'subscription-variation') ) ? wc_get_product( $product->get_parent_id() ) : $product ); |
| 646 |
/** |
| 647 |
* 1. Check for product exclusion |
| 648 |
* |
| 649 |
* If the product in exclusion - pricing rule does not match immediately |
| 650 |
*/ |
| 651 |
if ( !empty( $this->getExcludedProducts() ) ) { |
| 652 |
if ( in_array( $product->get_id(), $this->getExcludedProducts() ) || in_array( $parentProduct->get_id(), $this->getExcludedProducts() ) ) { |
| 653 |
return false; |
| 654 |
} |
| 655 |
} |
| 656 |
if ( !empty( $this->getExcludedProductCategories() ) ) { |
| 657 |
if ( !empty( array_intersect( $parentProduct->get_category_ids(), $this->getExcludedProductCategories() ) ) ) { |
| 658 |
return false; |
| 659 |
} |
| 660 |
} |
| 661 |
if ( !empty( $this->getExcludedProductTags() ) ) { |
| 662 |
if ( !empty( array_intersect( $parentProduct->get_tag_ids(), $this->getExcludedProductTags() ) ) ) { |
| 663 |
return false; |
| 664 |
} |
| 665 |
} |
| 666 |
if ( !empty( $this->getExcludedProductBrands() ) ) { |
| 667 |
$productBrands = wp_get_post_terms( $parentProduct->get_id(), 'product_brand', array( |
| 668 |
'fields' => 'ids', |
| 669 |
) ); |
| 670 |
if ( is_wp_error( $productBrands ) ) { |
| 671 |
$productBrands = []; |
| 672 |
} |
| 673 |
if ( !empty( array_intersect( $productBrands, $this->getExcludedProductBrands() ) ) ) { |
| 674 |
return false; |
| 675 |
} |
| 676 |
} |
| 677 |
/** |
| 678 |
* 2. Check for user exclusion |
| 679 |
* |
| 680 |
* If users in exclusion - pricing rule does not match immediately |
| 681 |
*/ |
| 682 |
if ( in_array( $user->ID, $this->getExcludedUsers() ) ) { |
| 683 |
return false; |
| 684 |
} |
| 685 |
foreach ( $this->getExcludedUserRoles() as $role ) { |
| 686 |
if ( in_array( $role, $user->roles ) ) { |
| 687 |
return false; |
| 688 |
} |
| 689 |
} |
| 690 |
/** |
| 691 |
* 3. Check for rule limitation for specific products |
| 692 |
* |
| 693 |
* If yes - match rule only for selected product/product categories |
| 694 |
*/ |
| 695 |
$productMatched = false; |
| 696 |
$productLimitations = false; |
| 697 |
if ( !empty( $this->getIncludedProducts() ) ) { |
| 698 |
$productLimitations = true; |
| 699 |
if ( in_array( $product->get_id(), $this->getIncludedProducts() ) || in_array( $parentProduct->get_id(), $this->getIncludedProducts() ) ) { |
| 700 |
$productMatched = true; |
| 701 |
} |
| 702 |
} |
| 703 |
if ( !empty( $this->getIncludedProductCategories() ) ) { |
| 704 |
$productLimitations = true; |
| 705 |
if ( !empty( array_intersect( $parentProduct->get_category_ids(), $this->getIncludedProductCategories() ) ) ) { |
| 706 |
$productMatched = true; |
| 707 |
} |
| 708 |
} |
| 709 |
if ( !empty( $this->getIncludedProductTags() ) ) { |
| 710 |
$productLimitations = true; |
| 711 |
if ( !empty( array_intersect( $parentProduct->get_tag_ids(), $this->getIncludedProductTags() ) ) ) { |
| 712 |
$productMatched = true; |
| 713 |
} |
| 714 |
} |
| 715 |
if ( !empty( $this->getIncludedProductBrands() ) ) { |
| 716 |
$productLimitations = true; |
| 717 |
$productBrands = wp_get_post_terms( $parentProduct->get_id(), 'product_brand', array( |
| 718 |
'fields' => 'ids', |
| 719 |
) ); |
| 720 |
if ( is_wp_error( $productBrands ) ) { |
| 721 |
$productBrands = []; |
| 722 |
} |
| 723 |
if ( !empty( array_intersect( $productBrands, $this->getIncludedProductBrands() ) ) ) { |
| 724 |
$productMatched = true; |
| 725 |
} |
| 726 |
} |
| 727 |
// There is product limitation and the product/category does not match the rule |
| 728 |
if ( $productLimitations && !$productMatched ) { |
| 729 |
return false; |
| 730 |
} |
| 731 |
/** |
| 732 |
* 4. If there are no user limits - match the rule immediately |
| 733 |
*/ |
| 734 |
if ( empty( $this->getIncludedUserRoles() ) && empty( $this->getIncludedUsers() ) ) { |
| 735 |
return true; |
| 736 |
} |
| 737 |
/** |
| 738 |
* 5. If there are user limits - check for user ID and user role. |
| 739 |
*/ |
| 740 |
if ( in_array( $user->ID, $this->getIncludedUsers() ) ) { |
| 741 |
return true; |
| 742 |
} |
| 743 |
foreach ( $this->getIncludedUserRoles() as $role ) { |
| 744 |
if ( in_array( $role, $user->roles ) ) { |
| 745 |
return true; |
| 746 |
} |
| 747 |
} |
| 748 |
return false; |
| 749 |
} |
| 750 |
|
| 751 |
} |
| 752 |
|