Version Description
- Fix links to premium plugins
Download this release
Release Info
Developer | dangoodman |
Plugin | WooCommerce Weight Based Shipping |
Version | 4.2.3 |
Comparing to | |
See all releases |
Version 4.2.3
- Model/WbsBucketRate.php +56 -0
- Model/WbsBucketRates.php +27 -0
- Model/WbsItemBucket.php +34 -0
- Model/WbsPackage.php +54 -0
- Model/WbsPackageLine.php +36 -0
- Model/WbsProgressiveRate.php +69 -0
- Model/WbsRange.php +80 -0
- Upgrade/WBS_Upgrade_Notice.php +44 -0
- Upgrade/WBS_Upgrade_Notices.php +119 -0
- WBS_Loader.php +115 -0
- WBS_Profile_Manager.php +180 -0
- WBS_Upgrader.php +257 -0
- WC_Weight_Based_Shipping.php +797 -0
- WbsFactory.php +14 -0
- WbsRuleUrls.php +55 -0
- WbsRulesOrderStorage.php +60 -0
- WbsSettingsHtmlTools.php +483 -0
- WbsWcTools.php +19 -0
- assets/admin.js +37 -0
- bootstrap.php +12 -0
- functions.php +37 -0
- legacy.php +38 -0
- readme.txt +177 -0
Model/WbsBucketRate.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WbsBucketRate
|
3 |
+
{
|
4 |
+
public function __construct($id, $flatRate, WbsProgressiveRate $progressiveRate)
|
5 |
+
{
|
6 |
+
$this->setId($id);
|
7 |
+
$this->setFlatRate($flatRate);
|
8 |
+
$this->setProgressiveRate($progressiveRate);
|
9 |
+
}
|
10 |
+
|
11 |
+
public function rate($amount)
|
12 |
+
{
|
13 |
+
return $this->flatRate + $this->progressiveRate->rate($amount);
|
14 |
+
}
|
15 |
+
|
16 |
+
public function getId()
|
17 |
+
{
|
18 |
+
return $this->id;
|
19 |
+
}
|
20 |
+
|
21 |
+
public function getFlatRate()
|
22 |
+
{
|
23 |
+
return $this->flatRate;
|
24 |
+
}
|
25 |
+
|
26 |
+
public function getProgressiveRate()
|
27 |
+
{
|
28 |
+
return $this->progressiveRate;
|
29 |
+
}
|
30 |
+
|
31 |
+
|
32 |
+
private $id;
|
33 |
+
private $flatRate;
|
34 |
+
/** @var WbsProgressiveRate */
|
35 |
+
private $progressiveRate;
|
36 |
+
|
37 |
+
private function setId($id)
|
38 |
+
{
|
39 |
+
if (empty($id)) {
|
40 |
+
throw new InvalidArgumentException("Please provide id for bucket rate");
|
41 |
+
}
|
42 |
+
|
43 |
+
$this->id = $id;
|
44 |
+
}
|
45 |
+
|
46 |
+
private function setFlatRate($rate)
|
47 |
+
{
|
48 |
+
$this->flatRate = (float)$rate;
|
49 |
+
}
|
50 |
+
|
51 |
+
private function setProgressiveRate(WbsProgressiveRate $rate)
|
52 |
+
{
|
53 |
+
$this->progressiveRate = $rate;
|
54 |
+
}
|
55 |
+
}
|
56 |
+
?>
|
Model/WbsBucketRates.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WbsBucketRates
|
3 |
+
{
|
4 |
+
/** @var WbsBucketRate[] */
|
5 |
+
private $rates;
|
6 |
+
|
7 |
+
public function __construct()
|
8 |
+
{
|
9 |
+
$this->rates = array();
|
10 |
+
}
|
11 |
+
|
12 |
+
public function add(WbsBucketRate $rate)
|
13 |
+
{
|
14 |
+
$this->rates[$rate->getId()] = $rate;
|
15 |
+
}
|
16 |
+
|
17 |
+
public function findById($class)
|
18 |
+
{
|
19 |
+
return @$this->rates[$class];
|
20 |
+
}
|
21 |
+
|
22 |
+
public function listAll()
|
23 |
+
{
|
24 |
+
return $this->rates;
|
25 |
+
}
|
26 |
+
}
|
27 |
+
?>
|
Model/WbsItemBucket.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WbsItemBucket
|
3 |
+
{
|
4 |
+
/** @var WbsBucketRate */
|
5 |
+
private $rate;
|
6 |
+
private $quantity;
|
7 |
+
|
8 |
+
public function __construct($quantity, WbsBucketRate $rate)
|
9 |
+
{
|
10 |
+
$this->rate = $rate;
|
11 |
+
$this->quantity = (float)$quantity;
|
12 |
+
}
|
13 |
+
|
14 |
+
public function calculate()
|
15 |
+
{
|
16 |
+
return $this->rate->rate($this->quantity);
|
17 |
+
}
|
18 |
+
|
19 |
+
public function add($quantity)
|
20 |
+
{
|
21 |
+
$this->quantity += $quantity;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getRate()
|
25 |
+
{
|
26 |
+
return $this->rate;
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getQuantity()
|
30 |
+
{
|
31 |
+
return $this->quantity;
|
32 |
+
}
|
33 |
+
}
|
34 |
+
?>
|
Model/WbsPackage.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WbsPackage
|
4 |
+
{
|
5 |
+
public function __construct(array $lines)
|
6 |
+
{
|
7 |
+
$this->lines = $lines;
|
8 |
+
}
|
9 |
+
|
10 |
+
public static function fromWcPackage(array $wcPackageData)
|
11 |
+
{
|
12 |
+
$lines = array();
|
13 |
+
foreach ($wcPackageData['contents'] as $wcLineData) {
|
14 |
+
$lines[] = new WbsPackageLine(
|
15 |
+
$wcLineData['data'],
|
16 |
+
$wcLineData['quantity'],
|
17 |
+
$wcLineData['line_subtotal'],
|
18 |
+
$wcLineData['line_subtotal_tax']
|
19 |
+
);
|
20 |
+
}
|
21 |
+
|
22 |
+
return new self($lines);
|
23 |
+
}
|
24 |
+
|
25 |
+
public function getLines()
|
26 |
+
{
|
27 |
+
return $this->lines;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function getPrice($withTax = true)
|
31 |
+
{
|
32 |
+
$price = 0;
|
33 |
+
|
34 |
+
foreach ($this->lines as $line) {
|
35 |
+
$price += $line->getPrice($withTax);
|
36 |
+
}
|
37 |
+
|
38 |
+
return $price;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function getWeight()
|
42 |
+
{
|
43 |
+
$weight = 0;
|
44 |
+
|
45 |
+
foreach ($this->lines as $line) {
|
46 |
+
$weight += $line->getWeight();
|
47 |
+
}
|
48 |
+
|
49 |
+
return $weight;
|
50 |
+
}
|
51 |
+
|
52 |
+
/** @var WbsPackageLine[] */
|
53 |
+
private $lines;
|
54 |
+
}
|
Model/WbsPackageLine.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WbsPackageLine
|
4 |
+
{
|
5 |
+
public function __construct(WC_Product $product, $quantity, $subtotal, $tax)
|
6 |
+
{
|
7 |
+
$this->product = $product;
|
8 |
+
$this->quantity = $quantity;
|
9 |
+
$this->subtotal = $subtotal;
|
10 |
+
$this->tax = $tax;
|
11 |
+
}
|
12 |
+
|
13 |
+
public function getQuantity()
|
14 |
+
{
|
15 |
+
return $this->quantity;
|
16 |
+
}
|
17 |
+
|
18 |
+
public function getProduct()
|
19 |
+
{
|
20 |
+
return $this->product;
|
21 |
+
}
|
22 |
+
|
23 |
+
public function getWeight()
|
24 |
+
{
|
25 |
+
return (float)$this->product->get_weight() * $this->quantity;
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getPrice($withTax = false)
|
29 |
+
{
|
30 |
+
return $this->subtotal + ($withTax ? $this->tax : 0);
|
31 |
+
}
|
32 |
+
|
33 |
+
private $product;
|
34 |
+
private $subtotal;
|
35 |
+
private $tax;
|
36 |
+
}
|
Model/WbsProgressiveRate.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WbsProgressiveRate
|
3 |
+
{
|
4 |
+
public function __construct($cost = 0, $step = 0, $skip = 0)
|
5 |
+
{
|
6 |
+
$cost = isset($cost) ? $cost : 0;
|
7 |
+
$step = isset($step) ? $step : 0;
|
8 |
+
$skip = isset($skip) ? $skip : 0;
|
9 |
+
|
10 |
+
if (!is_numeric($cost) || !is_numeric($step) || !is_numeric($skip)) {
|
11 |
+
throw new InvalidArgumentException(sprintf(
|
12 |
+
"%s: invalid argument value(s): '%s', '%s', '%s'.",
|
13 |
+
get_class(), var_export($cost, true), var_export($step, true), var_export($skip, true)
|
14 |
+
));
|
15 |
+
}
|
16 |
+
|
17 |
+
$this->cost = $cost;
|
18 |
+
$this->step = $step;
|
19 |
+
$this->skip = $skip;
|
20 |
+
}
|
21 |
+
|
22 |
+
public static function fromArray(array $input)
|
23 |
+
{
|
24 |
+
return new self(
|
25 |
+
@$input['cost'],
|
26 |
+
@$input['step'],
|
27 |
+
@$input['skip']
|
28 |
+
);
|
29 |
+
}
|
30 |
+
|
31 |
+
public function toArray()
|
32 |
+
{
|
33 |
+
return array(
|
34 |
+
'cost' => $this->cost,
|
35 |
+
'step' => $this->step,
|
36 |
+
'skip' => $this->skip,
|
37 |
+
);
|
38 |
+
}
|
39 |
+
|
40 |
+
public function rate($amount)
|
41 |
+
{
|
42 |
+
$amount = max(0, $amount - $this->skip);
|
43 |
+
|
44 |
+
if ($this->step != 0) {
|
45 |
+
$amount = ceil(round($amount / $this->step, 5));
|
46 |
+
}
|
47 |
+
|
48 |
+
return $amount * $this->cost;
|
49 |
+
}
|
50 |
+
|
51 |
+
public function getCost()
|
52 |
+
{
|
53 |
+
return $this->cost;
|
54 |
+
}
|
55 |
+
|
56 |
+
public function getStep()
|
57 |
+
{
|
58 |
+
return $this->step;
|
59 |
+
}
|
60 |
+
|
61 |
+
public function getSkip()
|
62 |
+
{
|
63 |
+
return $this->skip;
|
64 |
+
}
|
65 |
+
|
66 |
+
private $cost;
|
67 |
+
private $step;
|
68 |
+
private $skip;
|
69 |
+
}
|
Model/WbsRange.php
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* @property-read float $min
|
5 |
+
* @property-read float $max
|
6 |
+
* @property-read bool $minInclusive
|
7 |
+
* @property-read bool $maxInclusive
|
8 |
+
*/
|
9 |
+
class WbsRange
|
10 |
+
{
|
11 |
+
public function __construct($min = null, $max = null, $minInclusive = true, $maxInclusive = false)
|
12 |
+
{
|
13 |
+
$this->min = isset($min) ? (float)$min : null;
|
14 |
+
$this->max = isset($max) ? (float)$max : null;
|
15 |
+
$this->minInclusive = isset($minInclusive) ? !!$minInclusive : true;
|
16 |
+
$this->maxInclusive = isset($maxInclusive) ? !!$maxInclusive : false;
|
17 |
+
}
|
18 |
+
|
19 |
+
public static function fromArray(array $range)
|
20 |
+
{
|
21 |
+
return new self(
|
22 |
+
@$range['min']['value'],
|
23 |
+
@$range['max']['value'],
|
24 |
+
@$range['min']['inclusive'],
|
25 |
+
@$range['max']['inclusive']
|
26 |
+
);
|
27 |
+
}
|
28 |
+
|
29 |
+
public function toArray()
|
30 |
+
{
|
31 |
+
return array(
|
32 |
+
'min' => array(
|
33 |
+
'value' => $this->min,
|
34 |
+
'inclusive' => $this->minInclusive,
|
35 |
+
),
|
36 |
+
'max' => array(
|
37 |
+
'value' => $this->max,
|
38 |
+
'inclusive' => $this->maxInclusive,
|
39 |
+
),
|
40 |
+
);
|
41 |
+
}
|
42 |
+
|
43 |
+
public function includes($value)
|
44 |
+
{
|
45 |
+
if (isset($this->min) && ($value == $this->min && !$this->minInclusive || $value < $this->min) ||
|
46 |
+
isset($this->max) && ($value == $this->max && !$this->maxInclusive || $value > $this->max) ) {
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
|
50 |
+
return true;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function clamp($value)
|
54 |
+
{
|
55 |
+
if (isset($this->min) && $value < $this->min) {
|
56 |
+
$value = $this->min;
|
57 |
+
}
|
58 |
+
|
59 |
+
if (isset($this->max) && $value > $this->max) {
|
60 |
+
$value = $this->max;
|
61 |
+
}
|
62 |
+
|
63 |
+
return $value;
|
64 |
+
}
|
65 |
+
|
66 |
+
public function __get($property)
|
67 |
+
{
|
68 |
+
return $this->{$property};
|
69 |
+
}
|
70 |
+
|
71 |
+
public function __isset($property)
|
72 |
+
{
|
73 |
+
return isset($this->{$property});
|
74 |
+
}
|
75 |
+
|
76 |
+
private $min;
|
77 |
+
private $max;
|
78 |
+
private $minInclusive;
|
79 |
+
private $maxInclusive;
|
80 |
+
}
|
Upgrade/WBS_Upgrade_Notice.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WBS_Upgrade_Notice
|
3 |
+
{
|
4 |
+
private $shortHtml;
|
5 |
+
private $longHtml;
|
6 |
+
|
7 |
+
public static function createBehaviourChangeNotice($since, $message)
|
8 |
+
{
|
9 |
+
$shortHtml =
|
10 |
+
"Behavior of WooCommerce Weight Based Shipping changed since {$since}.";
|
11 |
+
|
12 |
+
$longHtml =
|
13 |
+
'<p>'.
|
14 |
+
esc_html($message).
|
15 |
+
'</p>
|
16 |
+
<p>'.
|
17 |
+
'Please <a href="'.esc_html(WbsRuleUrls::generic()).'">review settings</a>
|
18 |
+
and make appropriate changes if it\'s needed.'.
|
19 |
+
'</p>';
|
20 |
+
|
21 |
+
return new self($shortHtml, $longHtml);
|
22 |
+
}
|
23 |
+
|
24 |
+
public function __construct($shortHtml, $longHtml)
|
25 |
+
{
|
26 |
+
if (empty($shortHtml) || empty($longHtml)) {
|
27 |
+
throw new InvalidArgumentException();
|
28 |
+
}
|
29 |
+
|
30 |
+
$this->shortHtml = $shortHtml;
|
31 |
+
$this->longHtml = $longHtml;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function getShortHtml()
|
35 |
+
{
|
36 |
+
return $this->shortHtml;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function getLongHtml()
|
40 |
+
{
|
41 |
+
return $this->longHtml;
|
42 |
+
}
|
43 |
+
}
|
44 |
+
?>
|
Upgrade/WBS_Upgrade_Notices.php
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WBS_Upgrade_Notices
|
3 |
+
{
|
4 |
+
public function __construct($storageOptionName, $removeNoticeUrlFlagName)
|
5 |
+
{
|
6 |
+
$this->storageOptionName = $storageOptionName;
|
7 |
+
$this->removeNoticeUrlFlagName = $removeNoticeUrlFlagName;
|
8 |
+
}
|
9 |
+
|
10 |
+
public function add(WBS_Upgrade_Notice $notice)
|
11 |
+
{
|
12 |
+
$data = $this->load();
|
13 |
+
|
14 |
+
$data['last_id']++;
|
15 |
+
$data['notices'][$data['last_id']] = $notice;
|
16 |
+
|
17 |
+
$this->save($data);
|
18 |
+
|
19 |
+
return $data['last_id'];
|
20 |
+
}
|
21 |
+
|
22 |
+
public function remove($id)
|
23 |
+
{
|
24 |
+
$data = $this->load();
|
25 |
+
if (!isset($data['notices'][$id])) {
|
26 |
+
return false;
|
27 |
+
}
|
28 |
+
|
29 |
+
unset($data['notices'][$id]);
|
30 |
+
|
31 |
+
$this->save($data);
|
32 |
+
|
33 |
+
return true;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function show()
|
37 |
+
{
|
38 |
+
static $firstRun = true;
|
39 |
+
|
40 |
+
$data = $this->load();
|
41 |
+
|
42 |
+
/** @var WBS_Upgrade_Notice $notice */
|
43 |
+
foreach ($data['notices'] as $id => $notice) {
|
44 |
+
$hideNoticeUrl = esc_html(
|
45 |
+
WbsRuleUrls::generic(array($this->removeNoticeUrlFlagName => $id))
|
46 |
+
);
|
47 |
+
|
48 |
+
echo '
|
49 |
+
<div class="woowbs-upgrade-notice highlight" style="padding: 1em; border: 1px solid red;">
|
50 |
+
<big>'.
|
51 |
+
$notice->getShortHtml().
|
52 |
+
' <a class="woowbs-upgrade-notice-switcher" href="#">Less</a>
|
53 |
+
</big>
|
54 |
+
<div class="woowbs-upgrade-notice-long-message">'.
|
55 |
+
$notice->getLongHtml().
|
56 |
+
' <p><a class="button" href="'.$hideNoticeUrl.'">Don\'t show this message again</a></p>
|
57 |
+
</div>
|
58 |
+
</div>
|
59 |
+
';
|
60 |
+
|
61 |
+
if ($firstRun) {
|
62 |
+
$firstRun = false;
|
63 |
+
echo '
|
64 |
+
<script>
|
65 |
+
jQuery(function($) {
|
66 |
+
var toggleSpeed = 0;
|
67 |
+
var $collapsers = $(".woowbs-upgrade-notice-switcher");
|
68 |
+
|
69 |
+
$collapsers.click(function() {
|
70 |
+
var $collapser = $(this);
|
71 |
+
|
72 |
+
var $content = $collapser
|
73 |
+
.closest(".woowbs-upgrade-notice")
|
74 |
+
.find(".woowbs-upgrade-notice-long-message");
|
75 |
+
|
76 |
+
$content.toggle(toggleSpeed, function() {
|
77 |
+
$collapser.text($content.is(":visible") ? "Less" : "More");
|
78 |
+
});
|
79 |
+
|
80 |
+
return false;
|
81 |
+
});
|
82 |
+
|
83 |
+
$collapsers.click();
|
84 |
+
toggleSpeed = "fast";
|
85 |
+
});
|
86 |
+
</script>
|
87 |
+
';
|
88 |
+
}
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
public function getRemoveNoticeUrlFlagName()
|
93 |
+
{
|
94 |
+
return $this->removeNoticeUrlFlagName;
|
95 |
+
}
|
96 |
+
|
97 |
+
private $storageOptionName;
|
98 |
+
private $removeNoticeUrlFlagName;
|
99 |
+
|
100 |
+
private function load()
|
101 |
+
{
|
102 |
+
$data = get_option($this->storageOptionName, null);
|
103 |
+
|
104 |
+
if (!isset($data)) {
|
105 |
+
$data = array(
|
106 |
+
'last_id' => 0,
|
107 |
+
'notices' => array(),
|
108 |
+
);
|
109 |
+
}
|
110 |
+
|
111 |
+
return $data;
|
112 |
+
}
|
113 |
+
|
114 |
+
private function save(array $data)
|
115 |
+
{
|
116 |
+
update_option($this->storageOptionName, $data);
|
117 |
+
}
|
118 |
+
}
|
119 |
+
?>
|
WBS_Loader.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WBS_Loader
|
3 |
+
{
|
4 |
+
const ADMIN_SECTION_NAME = 'wc_weight_based_shipping';
|
5 |
+
|
6 |
+
public static function loadWbs($pluginFile)
|
7 |
+
{
|
8 |
+
if (!self::$loaded) {
|
9 |
+
self::$loaded = true;
|
10 |
+
new WBS_Loader($pluginFile);
|
11 |
+
}
|
12 |
+
}
|
13 |
+
|
14 |
+
public function __construct($pluginFile)
|
15 |
+
{
|
16 |
+
$this->pluginFile = wp_normalize_path($pluginFile);
|
17 |
+
add_action('plugins_loaded', array($this, 'load'), 0);
|
18 |
+
add_filter('plugin_action_links_' . plugin_basename($this->pluginFile), array($this, '_outputSettingsLink'));
|
19 |
+
}
|
20 |
+
|
21 |
+
public function load()
|
22 |
+
{
|
23 |
+
if (!$this->woocommerceAvailable()) return;
|
24 |
+
$this->loadLanguage();
|
25 |
+
$this->loadFunctions();
|
26 |
+
$this->loadClasses();
|
27 |
+
WBS_Profile_Manager::setup();
|
28 |
+
WBS_Upgrader::setup($this->pluginFile);
|
29 |
+
add_filter('woocommerce_get_sections_shipping', array($this, '_fixShippingMethodsLinks'));
|
30 |
+
|
31 |
+
if (is_admin()) {
|
32 |
+
|
33 |
+
add_action('wp_ajax_woowbs_update_rules_order', array($this, '_updateRulesOrder'));
|
34 |
+
|
35 |
+
if (@$_GET['section'] === self::ADMIN_SECTION_NAME) {
|
36 |
+
add_action('admin_enqueue_scripts', array($this, '_enqueueScripts'));
|
37 |
+
}
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
public function _outputSettingsLink($links)
|
42 |
+
{
|
43 |
+
array_unshift($links, '<a href="'.esc_html(WbsRuleUrls::generic()).'">'.__('Settings', 'woowbs').'</a>');
|
44 |
+
return $links;
|
45 |
+
}
|
46 |
+
|
47 |
+
public function _fixShippingMethodsLinks($sections)
|
48 |
+
{
|
49 |
+
foreach (WBS_Profile_Manager::instance()->profiles() as $profile) {
|
50 |
+
unset($sections[$profile->id]);
|
51 |
+
}
|
52 |
+
|
53 |
+
$sections[self::ADMIN_SECTION_NAME] = WC_Weight_Based_Shipping::getTitle();
|
54 |
+
|
55 |
+
return $sections;
|
56 |
+
}
|
57 |
+
|
58 |
+
public function _loadClass($class)
|
59 |
+
{
|
60 |
+
foreach ($this->classDirs as $dir) {
|
61 |
+
if (file_exists($file = "{$dir}/{$class}.php")) {
|
62 |
+
require_once($file);
|
63 |
+
return true;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
if (in_array($class, array('WBS_Shipping_Rate_Override', 'WBS_Shipping_Class_Override_Set'))) {
|
68 |
+
/** @noinspection PhpIncludeInspection */
|
69 |
+
require_once($this->legacyClassesFile);
|
70 |
+
}
|
71 |
+
|
72 |
+
return false;
|
73 |
+
}
|
74 |
+
|
75 |
+
public function _enqueueScripts()
|
76 |
+
{
|
77 |
+
wp_enqueue_script('woowbs-admin', plugins_url('assets/admin.js', $this->pluginFile), array('jquery-ui-sortable'));
|
78 |
+
wp_localize_script('woowbs-admin', 'woowbs_ajax_vars', array('ajax_url' => admin_url('admin-ajax.php')));
|
79 |
+
}
|
80 |
+
|
81 |
+
public function _updateRulesOrder() {
|
82 |
+
$order = WbsFactory::getRulesOrderStorage();
|
83 |
+
$order->set($_POST['profiles']);
|
84 |
+
WbsWcTools::purgeWoocommerceShippingCache();
|
85 |
+
wp_die();
|
86 |
+
}
|
87 |
+
|
88 |
+
private static $loaded;
|
89 |
+
private $pluginFile;
|
90 |
+
private $classDirs;
|
91 |
+
private $legacyClassesFile;
|
92 |
+
|
93 |
+
private function woocommerceAvailable()
|
94 |
+
{
|
95 |
+
return class_exists('WC_Shipping_Method');
|
96 |
+
}
|
97 |
+
|
98 |
+
private function loadLanguage()
|
99 |
+
{
|
100 |
+
load_plugin_textdomain('woowbs', false, dirname(plugin_basename($this->pluginFile)).'/lang/');
|
101 |
+
}
|
102 |
+
|
103 |
+
private function loadFunctions()
|
104 |
+
{
|
105 |
+
require_once(dirname(__FILE__) . "/functions.php");
|
106 |
+
}
|
107 |
+
|
108 |
+
private function loadClasses()
|
109 |
+
{
|
110 |
+
$wbsdir = dirname(__FILE__);
|
111 |
+
$this->classDirs = array($wbsdir, "{$wbsdir}/Model", "{$wbsdir}/Upgrade");
|
112 |
+
$this->legacyClassesFile = "{$wbsdir}/legacy.php";
|
113 |
+
spl_autoload_register(array($this, '_loadClass'));
|
114 |
+
}
|
115 |
+
}
|
WBS_Profile_Manager.php
ADDED
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WBS_Profile_Manager
|
3 |
+
{
|
4 |
+
public static function setup()
|
5 |
+
{
|
6 |
+
self::instance();
|
7 |
+
}
|
8 |
+
|
9 |
+
public static function instance($resetCache = false)
|
10 |
+
{
|
11 |
+
if (!isset(self::$instance)) {
|
12 |
+
self::$instance = new self();
|
13 |
+
add_filter('woocommerce_shipping_methods', array(self::$instance, '_registerProfiles'));
|
14 |
+
}
|
15 |
+
|
16 |
+
if ($resetCache) {
|
17 |
+
unset(self::$instance->orderedProfiles);
|
18 |
+
unset(self::$instance->profileInstances);
|
19 |
+
}
|
20 |
+
|
21 |
+
return self::$instance;
|
22 |
+
}
|
23 |
+
|
24 |
+
/** @return WC_Weight_Based_Shipping[] */
|
25 |
+
public function profiles()
|
26 |
+
{
|
27 |
+
if (!isset($this->orderedProfiles)) {
|
28 |
+
|
29 |
+
$this->orderedProfiles = array();
|
30 |
+
|
31 |
+
/** @var WC_Shipping $shipping */
|
32 |
+
$shipping = WC()->shipping;
|
33 |
+
foreach ($shipping->load_shipping_methods() as $method)
|
34 |
+
{
|
35 |
+
if ($method instanceof WC_Weight_Based_Shipping)
|
36 |
+
{
|
37 |
+
$this->orderedProfiles[] = $method;
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
return $this->orderedProfiles;
|
43 |
+
}
|
44 |
+
|
45 |
+
public function profile($name = null)
|
46 |
+
{
|
47 |
+
$this->find_suitable_id($name);
|
48 |
+
$profiles = $this->instantiateProfiles();
|
49 |
+
return @$profiles[$name];
|
50 |
+
}
|
51 |
+
|
52 |
+
public function profile_exists($name)
|
53 |
+
{
|
54 |
+
$profiles = $this->instantiateProfiles();
|
55 |
+
return isset($profiles[$name]);
|
56 |
+
}
|
57 |
+
|
58 |
+
public function find_suitable_id(&$profileId)
|
59 |
+
{
|
60 |
+
if (!$profileId && !($profileId = $this->current_profile_id())) {
|
61 |
+
return $profileId = null;
|
62 |
+
}
|
63 |
+
|
64 |
+
return $profileId;
|
65 |
+
}
|
66 |
+
|
67 |
+
public function current_profile_id()
|
68 |
+
{
|
69 |
+
$profile_id = null;
|
70 |
+
|
71 |
+
if (is_admin()) {
|
72 |
+
|
73 |
+
if (empty($profile_id)) {
|
74 |
+
$profile_id = @$_GET['wbs_profile'];
|
75 |
+
}
|
76 |
+
|
77 |
+
if (empty($profile_id) && ($profiles = $this->profiles())) {
|
78 |
+
$profile_id = $profiles[0]->profile_id;
|
79 |
+
}
|
80 |
+
|
81 |
+
if (empty($profile_id)) {
|
82 |
+
$profile_id = 'main';
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
return $profile_id;
|
87 |
+
}
|
88 |
+
|
89 |
+
public function new_profile_id()
|
90 |
+
{
|
91 |
+
if (!$this->profile_exists('main')) {
|
92 |
+
return 'main';
|
93 |
+
}
|
94 |
+
|
95 |
+
$timestamp = time();
|
96 |
+
|
97 |
+
$i = null;
|
98 |
+
do {
|
99 |
+
$new_profile_id = trim($timestamp.'-'.$i++, '-');
|
100 |
+
} while ($this->profile_exists($new_profile_id));
|
101 |
+
|
102 |
+
return $new_profile_id;
|
103 |
+
}
|
104 |
+
|
105 |
+
|
106 |
+
|
107 |
+
public function _registerProfiles($methods)
|
108 |
+
{
|
109 |
+
return array_merge($methods, $this->instantiateProfiles());
|
110 |
+
}
|
111 |
+
|
112 |
+
public static function listAvailableProfileIds($pluginPrefix = WC_Weight_Based_Shipping::PLUGIN_PREFIX, $idPrefix = null)
|
113 |
+
{
|
114 |
+
$ids = array();
|
115 |
+
|
116 |
+
$settingsOptionNamePattern = sprintf('/^%s%s(\\w+)_settings$/',
|
117 |
+
preg_quote($pluginPrefix, '/'), preg_quote($idPrefix, '/')
|
118 |
+
);
|
119 |
+
|
120 |
+
foreach (array_keys(wp_load_alloptions()) as $option) {
|
121 |
+
$matches = array();
|
122 |
+
if (preg_match($settingsOptionNamePattern, $option, $matches)) {
|
123 |
+
$ids[] = $matches[1];
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
$ids = WbsFactory::getRulesOrderStorage()->sort($ids);
|
128 |
+
|
129 |
+
return $ids;
|
130 |
+
}
|
131 |
+
|
132 |
+
public static function getRuleSettingsOptionName($ruleId, $pluginPrefix = WC_Weight_Based_Shipping::PLUGIN_PREFIX)
|
133 |
+
{
|
134 |
+
return sprintf('%s%s_settings', $pluginPrefix, $ruleId);
|
135 |
+
}
|
136 |
+
|
137 |
+
|
138 |
+
private static $instance;
|
139 |
+
|
140 |
+
private $orderedProfiles;
|
141 |
+
|
142 |
+
/** @var WC_Weight_Based_Shipping[] */
|
143 |
+
private $profileInstances;
|
144 |
+
|
145 |
+
private function instantiateProfiles()
|
146 |
+
{
|
147 |
+
if (!isset($this->profileInstances)) {
|
148 |
+
|
149 |
+
$this->profileInstances = array();
|
150 |
+
|
151 |
+
$profileIds = self::listAvailableProfileIds();
|
152 |
+
if (empty($profileIds)) {
|
153 |
+
$profileIds[] = $this->new_profile_id();
|
154 |
+
}
|
155 |
+
|
156 |
+
foreach ($profileIds as $profileId) {
|
157 |
+
$this->profileInstances[$profileId] = new WC_Weight_Based_Shipping($profileId);
|
158 |
+
}
|
159 |
+
|
160 |
+
if (is_admin() &&
|
161 |
+
($editingProfileId = @$_GET['wbs_profile']) &&
|
162 |
+
!isset($this->profileInstances[$editingProfileId])) {
|
163 |
+
|
164 |
+
$editingProfile = new WC_Weight_Based_Shipping($editingProfileId);
|
165 |
+
$editingProfile->_stub = true;
|
166 |
+
$this->profileInstances[$editingProfileId] = $editingProfile;
|
167 |
+
}
|
168 |
+
|
169 |
+
if ($currentProfile = $this->profile()) {
|
170 |
+
add_action(
|
171 |
+
'woocommerce_update_options_shipping_' . $currentProfile->id,
|
172 |
+
array($currentProfile, 'process_admin_options')
|
173 |
+
);
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
return $this->profileInstances;
|
178 |
+
}
|
179 |
+
}
|
180 |
+
?>
|
WBS_Upgrader.php
ADDED
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WBS_Upgrader
|
3 |
+
{
|
4 |
+
public static function setup($pluginFile)
|
5 |
+
{
|
6 |
+
if (!isset(self::$instance)) {
|
7 |
+
$upgrader = new self($pluginFile);
|
8 |
+
$upgrader->onLoad();
|
9 |
+
self::$instance = $upgrader;
|
10 |
+
}
|
11 |
+
}
|
12 |
+
|
13 |
+
public static function instance()
|
14 |
+
{
|
15 |
+
return self::$instance;
|
16 |
+
}
|
17 |
+
|
18 |
+
public function __construct($pluginFile)
|
19 |
+
{
|
20 |
+
$this->pluginFile = $pluginFile;
|
21 |
+
$this->upgradeNotices = new WBS_Upgrade_Notices('woowbs_upgrade_notices', 'woowbs_remove_upgrade_notice');
|
22 |
+
}
|
23 |
+
|
24 |
+
public function onLoad()
|
25 |
+
{
|
26 |
+
$this->setupHooks();
|
27 |
+
}
|
28 |
+
|
29 |
+
public function onAdminInit()
|
30 |
+
{
|
31 |
+
$this->checkForUpgrade();
|
32 |
+
}
|
33 |
+
|
34 |
+
public function onAdminNotices()
|
35 |
+
{
|
36 |
+
$this->upgradeNotices->show();
|
37 |
+
}
|
38 |
+
|
39 |
+
public function removeUpgradeNotices()
|
40 |
+
{
|
41 |
+
$id = @$_GET[$this->upgradeNotices->getRemoveNoticeUrlFlagName()];
|
42 |
+
if (!isset($id)) {
|
43 |
+
return false;
|
44 |
+
}
|
45 |
+
|
46 |
+
return $this->upgradeNotices->remove($id);
|
47 |
+
}
|
48 |
+
|
49 |
+
/** @var WBS_Upgrader */
|
50 |
+
private static $instance;
|
51 |
+
private $pluginFile;
|
52 |
+
private $upgradeNotices;
|
53 |
+
|
54 |
+
private function checkForUpgrade()
|
55 |
+
{
|
56 |
+
$updateCurrentVersion = false;
|
57 |
+
|
58 |
+
$currentVersion = null; {
|
59 |
+
$pluginData = get_plugin_data($this->pluginFile, false, false);
|
60 |
+
$currentVersion = $pluginData['Version'];
|
61 |
+
}
|
62 |
+
|
63 |
+
$previousVersion = get_option('woowbs_version');
|
64 |
+
if (empty($previousVersion)) {
|
65 |
+
$hasSomeRules = !!self::listAvailableProfileIds();
|
66 |
+
$hasSomeRules = $hasSomeRules || !!self::listAvailableProfileIds('woocommerce_', 'WC_Weight_Based_Shipping_');
|
67 |
+
$previousVersion = $hasSomeRules ? '2.6.8' : $currentVersion;
|
68 |
+
$updateCurrentVersion = true;
|
69 |
+
}
|
70 |
+
|
71 |
+
if ($previousVersion !== $currentVersion) {
|
72 |
+
|
73 |
+
$updateCurrentVersion = true;
|
74 |
+
|
75 |
+
if (version_compare($previousVersion, '2.2.1') < 0) {
|
76 |
+
$this->upgradeNotices->add(WBS_Upgrade_Notice::createBehaviourChangeNotice('2.2.1', '
|
77 |
+
Previously, weight-based shipping option has not been shown to user if total
|
78 |
+
weight of their cart is zero. Since version 2.2.1 this is changed so shipping
|
79 |
+
option is available to user with price set to Handling Fee. If it does not
|
80 |
+
suite your needs well you can return previous behavior by setting Min Weight
|
81 |
+
to something a bit greater zero, e.g. 0.001, so that zero-weight orders will
|
82 |
+
not match constraints and the shipping option will not be shown.
|
83 |
+
'));
|
84 |
+
}
|
85 |
+
|
86 |
+
if (version_compare($previousVersion, '2.4.0') < 0) {
|
87 |
+
$profiles = WBS_Profile_Manager::instance()->profiles();
|
88 |
+
foreach ($profiles as $profile) {
|
89 |
+
$option = $profile->get_wp_option_name();
|
90 |
+
$config = get_option($option);
|
91 |
+
$config['extra_weight_only'] = 'no';
|
92 |
+
update_option($option, $config);
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
if (version_compare($previousVersion, '2.6.3') < 0) {
|
97 |
+
$this->upgradeNotices->add(WBS_Upgrade_Notice::createBehaviourChangeNotice('2.6.2', '
|
98 |
+
Previously, base Handling Fee has not been added to the shipping price if user
|
99 |
+
cart contained only items with shipping classes specified in the Shipping
|
100 |
+
Classes Overrides section. Starting from version 2.6.2 base Handling Fee is
|
101 |
+
applied in any case. This behavior change is only affecting you if you use
|
102 |
+
Shipping Classes Overrides. If you don\'t use it just ignore this message.
|
103 |
+
'));
|
104 |
+
}
|
105 |
+
|
106 |
+
if (version_compare($previousVersion, '4.0.0') < 0) {
|
107 |
+
|
108 |
+
// Rename settings options
|
109 |
+
if ($ruleIdsToUpdate = self::listAvailableProfileIds('woocommerce_', 'WC_Weight_Based_Shipping_')) {
|
110 |
+
|
111 |
+
foreach ($ruleIdsToUpdate as $oldSettingsName => $id) {
|
112 |
+
|
113 |
+
$settings = get_option($oldSettingsName);
|
114 |
+
|
115 |
+
# Don't remove old settings entry. Keep it as a backup.
|
116 |
+
//delete_option($oldSettingsName);
|
117 |
+
|
118 |
+
$newSettingsName = WBS_Profile_Manager::getRuleSettingsOptionName($id);
|
119 |
+
if (!get_option($newSettingsName)) {
|
120 |
+
update_option($newSettingsName, $settings);
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
// Reset cache to load renamed rules
|
125 |
+
WBS_Profile_Manager::instance(true);
|
126 |
+
}
|
127 |
+
|
128 |
+
$rangeFieldsMap = array(
|
129 |
+
'weight' => array( 'min_weight', 'max_weight', false ),
|
130 |
+
'subtotal' => array( 'min_subtotal', 'max_subtotal', false ),
|
131 |
+
'price_clamp' => array( 'min_price', 'max_price', true ),
|
132 |
+
);
|
133 |
+
|
134 |
+
foreach (WBS_Profile_Manager::instance()->profiles() as $profile) {
|
135 |
+
|
136 |
+
$option = $profile->get_wp_option_name();
|
137 |
+
$config = get_option($option);
|
138 |
+
|
139 |
+
// Convert conditions
|
140 |
+
foreach ($rangeFieldsMap as $newField => $oldFields) {
|
141 |
+
|
142 |
+
if (!isset($config[$newField])) {
|
143 |
+
|
144 |
+
$range = null;
|
145 |
+
|
146 |
+
$min = (float)@$config[$oldFields[0]];
|
147 |
+
$max = (float)@$config[$oldFields[1]];
|
148 |
+
if ($min || $max) {
|
149 |
+
$range = new WbsRange(
|
150 |
+
$min ? $min : null,
|
151 |
+
$max ? $max : null,
|
152 |
+
true,
|
153 |
+
$oldFields[2] || !!$max
|
154 |
+
);
|
155 |
+
}
|
156 |
+
|
157 |
+
if (!isset($range)) {
|
158 |
+
$range = new WbsRange();
|
159 |
+
}
|
160 |
+
|
161 |
+
$config[$newField] = $range->toArray();
|
162 |
+
}
|
163 |
+
|
164 |
+
unset($config[$oldFields[0]]);
|
165 |
+
unset($config[$oldFields[1]]);
|
166 |
+
}
|
167 |
+
|
168 |
+
$weightRange = WbsRange::fromArray(@$config['weight']);
|
169 |
+
$extraWeightOnly = @$config['extra_weight_only'];
|
170 |
+
unset($config['extra_weight_only']);
|
171 |
+
|
172 |
+
// Convert progressive rate
|
173 |
+
if (!isset($config['weight_rate'])) {
|
174 |
+
|
175 |
+
$config['weight_rate'] = self::convertToProgressiveRate(
|
176 |
+
@$config['rate'],
|
177 |
+
@$config['weight_step'],
|
178 |
+
$extraWeightOnly,
|
179 |
+
$weightRange->min
|
180 |
+
)->toArray();
|
181 |
+
|
182 |
+
unset($config['weight_step']);
|
183 |
+
unset($config['rate']);
|
184 |
+
}
|
185 |
+
|
186 |
+
// Convert shipping class rates
|
187 |
+
if (!isset($config['shipping_class_rates'])) {
|
188 |
+
|
189 |
+
/** @var WBS_Shipping_Class_Override_Set $oldRates */
|
190 |
+
if (($oldRates = @$config['shipping_class_overrides']) &&
|
191 |
+
($oldRates = $oldRates->getOverrides())) {
|
192 |
+
|
193 |
+
$rates = new WbsBucketRates();
|
194 |
+
|
195 |
+
/** @var WBS_Shipping_Rate_Override $oldRate */
|
196 |
+
foreach ($oldRates as $oldRate) {
|
197 |
+
|
198 |
+
$rates->add(new WbsBucketRate(
|
199 |
+
$oldRate->getClass(),
|
200 |
+
$oldRate->getFee(),
|
201 |
+
self::convertToProgressiveRate(
|
202 |
+
$oldRate->getRate(),
|
203 |
+
@$oldRate->getWeightStep(),
|
204 |
+
$extraWeightOnly,
|
205 |
+
$weightRange->min
|
206 |
+
)
|
207 |
+
));
|
208 |
+
}
|
209 |
+
|
210 |
+
$config['shipping_class_rates'] = $rates;
|
211 |
+
}
|
212 |
+
|
213 |
+
unset($config['shipping_class_overrides']);
|
214 |
+
}
|
215 |
+
|
216 |
+
update_option($option, $config);
|
217 |
+
}
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
if ($updateCurrentVersion) {
|
222 |
+
update_option('woowbs_version', $currentVersion);
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
private function setupHooks()
|
227 |
+
{
|
228 |
+
add_action('admin_init', array($this, 'onAdminInit'));
|
229 |
+
add_action('admin_notices', array($this, 'onAdminNotices'));
|
230 |
+
}
|
231 |
+
|
232 |
+
private static function convertToProgressiveRate($rate, $weightStep, $extraWeightOnly, $minWeightRange)
|
233 |
+
{
|
234 |
+
$rate = $rate * ($weightStep ? $weightStep : 1);
|
235 |
+
$weightStep = $rate ? $weightStep : 0;
|
236 |
+
$skip = $rate && $extraWeightOnly !== 'no' ? $minWeightRange : 0;
|
237 |
+
return new WbsProgressiveRate($rate, $weightStep, $skip);
|
238 |
+
}
|
239 |
+
|
240 |
+
private static function listAvailableProfileIds($pluginPrefix = WC_Weight_Based_Shipping::PLUGIN_PREFIX, $idPrefix = null)
|
241 |
+
{
|
242 |
+
$ids = array();
|
243 |
+
|
244 |
+
$settingsOptionNamePattern = sprintf('/^%s%s(\\w+)_settings$/',
|
245 |
+
preg_quote($pluginPrefix, '/'), preg_quote($idPrefix, '/')
|
246 |
+
);
|
247 |
+
|
248 |
+
foreach (array_keys(wp_load_alloptions()) as $option) {
|
249 |
+
$matches = array();
|
250 |
+
if (preg_match($settingsOptionNamePattern, $option, $matches)) {
|
251 |
+
$ids[$matches[0]] = $matches[1];
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
return $ids;
|
256 |
+
}
|
257 |
+
}
|
WC_Weight_Based_Shipping.php
ADDED
@@ -0,0 +1,797 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WC_Weight_Based_Shipping extends WC_Shipping_Method
|
3 |
+
{
|
4 |
+
const PLUGIN_PREFIX = 'woowbs_';
|
5 |
+
|
6 |
+
public $plugin_id = self::PLUGIN_PREFIX;
|
7 |
+
|
8 |
+
public $name;
|
9 |
+
public $profile_id;
|
10 |
+
|
11 |
+
/** @var WbsRange */
|
12 |
+
public $weight;
|
13 |
+
/** @var WbsRange */
|
14 |
+
public $subtotal;
|
15 |
+
public $subtotalWithTax;
|
16 |
+
|
17 |
+
/** @var WbsProgressiveRate */
|
18 |
+
public $weightRate;
|
19 |
+
|
20 |
+
/** @var WbsBucketRates */
|
21 |
+
public $shippingClassRates;
|
22 |
+
|
23 |
+
/** @var WbsRange */
|
24 |
+
public $priceClamp;
|
25 |
+
|
26 |
+
public $valid = false;
|
27 |
+
|
28 |
+
public $_stub = false;
|
29 |
+
|
30 |
+
|
31 |
+
static public function getTitle()
|
32 |
+
{
|
33 |
+
return __('Weight Based', 'woowbs');
|
34 |
+
}
|
35 |
+
|
36 |
+
/** @noinspection PhpMissingParentConstructorInspection */
|
37 |
+
public function __construct($profileId = null)
|
38 |
+
{
|
39 |
+
$manager = WBS_Profile_Manager::instance();
|
40 |
+
|
41 |
+
// Force loading profiles when called from WooCommerce 2.3.9- save handler
|
42 |
+
// to activate process_admin_option() with appropriate hook
|
43 |
+
if (!isset($profileId)) {
|
44 |
+
$manager->profiles();
|
45 |
+
}
|
46 |
+
|
47 |
+
$this->id = $manager->find_suitable_id($profileId);
|
48 |
+
$this->profile_id = $profileId;
|
49 |
+
|
50 |
+
$this->method_title = self::getTitle();
|
51 |
+
|
52 |
+
$this->settingsHelper = new WbsSettingsHtmlTools($this);
|
53 |
+
|
54 |
+
$this->safeInit();
|
55 |
+
}
|
56 |
+
|
57 |
+
public function __clone()
|
58 |
+
{
|
59 |
+
$manager = WBS_Profile_Manager::instance();
|
60 |
+
|
61 |
+
$this->profile_id = $manager->new_profile_id();
|
62 |
+
$this->id = $manager->find_suitable_id($this->profile_id);
|
63 |
+
|
64 |
+
$this->name .= ' ('._x('copy', 'noun', 'woowbs').')';
|
65 |
+
$this->settings['name'] = $this->name;
|
66 |
+
|
67 |
+
$this->shippingClassRates = clone($this->shippingClassRates);
|
68 |
+
|
69 |
+
$this->settingsHelper = new WbsSettingsHtmlTools($this);
|
70 |
+
}
|
71 |
+
|
72 |
+
|
73 |
+
public function init_form_fields()
|
74 |
+
{
|
75 |
+
$woocommerce = WC();
|
76 |
+
$shippingCountries = method_exists($woocommerce->countries, 'get_shipping_countries')
|
77 |
+
? $woocommerce->countries->get_shipping_countries()
|
78 |
+
: $woocommerce->countries->{'countries'};
|
79 |
+
|
80 |
+
$this->form_fields = array(
|
81 |
+
### Meta ###
|
82 |
+
array(
|
83 |
+
'type' => 'title',
|
84 |
+
'title' => __('Rule Settings', 'woowbs'),
|
85 |
+
),
|
86 |
+
'enabled' => array(
|
87 |
+
'title' => __('Enable/Disable', 'woowbs'),
|
88 |
+
'type' => 'checkbox',
|
89 |
+
'label' => __('Enable this rule', 'woowbs'),
|
90 |
+
'default' => 'yes',
|
91 |
+
),
|
92 |
+
'name' => array(
|
93 |
+
'title' => __('Label', 'woowbs'),
|
94 |
+
'description' => __('This is an internal rule label, just for you. Customers don\'t see this.', 'woowbs'),
|
95 |
+
'type' => 'text',
|
96 |
+
'default' => sprintf($this->profile_id != 'main' ? __('rule #%s') : '%s', $this->profile_id),
|
97 |
+
),
|
98 |
+
'title' => array(
|
99 |
+
'title' => __('Title', 'woowbs'),
|
100 |
+
'type' => 'text',
|
101 |
+
'description' => __('This controls the title which the customer sees during checkout.', 'woowbs'),
|
102 |
+
'default' => __('Weight Based Shipping', 'woowbs'),
|
103 |
+
),
|
104 |
+
'tax_status' => array(
|
105 |
+
'title' => __('Tax Status', 'woowbs'),
|
106 |
+
'type' => 'select',
|
107 |
+
'default' => 'taxable',
|
108 |
+
'class' => 'availability wc-enhanced-select',
|
109 |
+
'options' => array(
|
110 |
+
'taxable' => __('Taxable', 'woowbs'),
|
111 |
+
'none' => __('None', 'woowbs'),
|
112 |
+
),
|
113 |
+
),
|
114 |
+
### Conditions ###
|
115 |
+
array(
|
116 |
+
'type' => 'title',
|
117 |
+
'title' => __('Conditions', 'woowbs'),
|
118 |
+
'description' => __('Define when the delivery option should be shown to the customer. All the following conditions must be met to activate the rule.', 'woowbs'),
|
119 |
+
),
|
120 |
+
'availability' => array(
|
121 |
+
'title' => __('Destination', 'woowbs'),
|
122 |
+
'type' => 'select',
|
123 |
+
'default' => 'all',
|
124 |
+
'class' => 'availability wc-enhanced-select',
|
125 |
+
'options' => array(
|
126 |
+
'all' => __('All allowed countries', 'woowbs'),
|
127 |
+
'specific' => __('Specific countries', 'woowbs'),
|
128 |
+
'excluding' => __('All countries except specific', 'woowbs'),
|
129 |
+
),
|
130 |
+
),
|
131 |
+
'countries' => array(
|
132 |
+
'title' => __('Specific Countries', 'woowbs'),
|
133 |
+
'type' => 'wbs_custom',
|
134 |
+
'wbs_real_type' => 'multiselect',
|
135 |
+
'wbs_row_class' => 'wbs-destination',
|
136 |
+
'class' => 'chosen_select',
|
137 |
+
'default' => '',
|
138 |
+
'options' => $shippingCountries,
|
139 |
+
'custom_attributes' => array(
|
140 |
+
'data-placeholder' => __('Select some countries', 'woowbs'),
|
141 |
+
),
|
142 |
+
'html' =>
|
143 |
+
'<a class="select_all button" href="#">'.__('Select all', 'woowbs').'</a> '.
|
144 |
+
'<a class="select_none button" href="#">'.__('Select none', 'woowbs').'</a>'.
|
145 |
+
$this->settingsHelper->premiumPromotionHtml('States/counties targeting'),
|
146 |
+
),
|
147 |
+
'weight' => array(
|
148 |
+
'title' => __('Order Weight', 'woowbs'),
|
149 |
+
'type' => 'wbs_range',
|
150 |
+
),
|
151 |
+
'subtotal' => array(
|
152 |
+
'title' => __('Order Subtotal', 'woowbs'),
|
153 |
+
'type' => 'wbs_custom',
|
154 |
+
'wbs_real_type' => 'wbs_range',
|
155 |
+
'wbs_row_class' => 'wbs-subtotal',
|
156 |
+
),
|
157 |
+
'subtotal_with_tax' => array(
|
158 |
+
'title' => __('Subtotal With Tax', 'woowbs'),
|
159 |
+
'type' => 'checkbox',
|
160 |
+
'label' => __('After tax included', 'woowbs'),
|
161 |
+
),
|
162 |
+
|
163 |
+
### Calculations ###
|
164 |
+
array(
|
165 |
+
'type' => 'title',
|
166 |
+
'title' => __('Costs', 'woowbs'),
|
167 |
+
'description' => __('This controls shipping price when this rule is active.', 'woowbs'),
|
168 |
+
),
|
169 |
+
'fee' => array(
|
170 |
+
'title' => __('Base Cost', 'woowbs'),
|
171 |
+
'type' => 'decimal',
|
172 |
+
'description' => __('Leave empty or zero if your shipping price has no flat part.', 'woowbs'),
|
173 |
+
),
|
174 |
+
'weight_rate' => array(
|
175 |
+
'title' => __('Weight Rate', 'woowbs'),
|
176 |
+
'type' => 'wbs_weight_rate',
|
177 |
+
'description' =>
|
178 |
+
__('Leave <code class="wbs-code">charge</code> field empty if your shipping price is flat.', 'woowbs').'<br>'.
|
179 |
+
__('Use <code class="wbs-code">over</code> field to skip weight part covered with Base Cost or leave it empty to charge for entire order weight.', 'woowbs'),
|
180 |
+
),
|
181 |
+
'shipping_class_rates' => array(
|
182 |
+
'title' => __('Shipping Classes', 'woowbs'),
|
183 |
+
'type' => 'shipping_class_rates',
|
184 |
+
'description' => __('You can override some options for specific shipping classes', 'woowbs'),
|
185 |
+
),
|
186 |
+
|
187 |
+
### Modificators ###
|
188 |
+
array(
|
189 |
+
'type' => 'title',
|
190 |
+
'title' => __('Modificators', 'woowbs'),
|
191 |
+
'description' => __('With the following you can modify resulting shipping price', 'woowbs'),
|
192 |
+
),
|
193 |
+
'price_clamp' => array(
|
194 |
+
'title' => __('Limit Total Cost', 'woowbs'),
|
195 |
+
'type' => 'wbs_range',
|
196 |
+
'wbs_range_type' => 'simple',
|
197 |
+
'description' => __('If total shipping price (Base Cost + Weight Rate) exceeds specified range it will be changed to the either lower or upper bound appropriately.', 'woowbs'),
|
198 |
+
),
|
199 |
+
);
|
200 |
+
|
201 |
+
$placeholders = array
|
202 |
+
(
|
203 |
+
'weight_unit' => __(get_option('woocommerce_weight_unit'), 'woowbs'),
|
204 |
+
'currency' => get_woocommerce_currency_symbol(),
|
205 |
+
);
|
206 |
+
|
207 |
+
foreach ($this->form_fields as &$field)
|
208 |
+
{
|
209 |
+
$field['description'] = wbst(@$field['description'], $placeholders);
|
210 |
+
}
|
211 |
+
|
212 |
+
$this->form_fields = apply_filters('wbs_profile_settings_form', $this->form_fields, $this);
|
213 |
+
}
|
214 |
+
|
215 |
+
public function calculate_shipping($package = array())
|
216 |
+
{
|
217 |
+
if (!$this->valid) {
|
218 |
+
wc_add_notice("Price of shipping method '{$this->name}' couldn't be calculated");
|
219 |
+
return;
|
220 |
+
}
|
221 |
+
|
222 |
+
$package = WbsPackage::fromWcPackage($package);
|
223 |
+
|
224 |
+
if (!$this->weight->includes($package->getWeight()) ||
|
225 |
+
!$this->subtotal->includes($package->getPrice($this->subtotalWithTax))) {
|
226 |
+
return;
|
227 |
+
}
|
228 |
+
|
229 |
+
$defaultRate = new WbsBucketRate(
|
230 |
+
'___wbs_base_pseudo_class',
|
231 |
+
$this->fee,
|
232 |
+
$this->weightRate
|
233 |
+
);
|
234 |
+
|
235 |
+
/** @var WbsItemBucket[] $buckets */
|
236 |
+
$buckets = array(); {
|
237 |
+
|
238 |
+
foreach ($package->getLines() as $line) {
|
239 |
+
|
240 |
+
$product = $line->getProduct();
|
241 |
+
$class = $product->get_shipping_class();
|
242 |
+
|
243 |
+
$rate = $this->shippingClassRates->findById($class);
|
244 |
+
if ($rate == null) {
|
245 |
+
$rate = $defaultRate;
|
246 |
+
}
|
247 |
+
|
248 |
+
$class = $rate->getId();
|
249 |
+
if (!isset($buckets[$class])) {
|
250 |
+
$buckets[$class] = new WbsItemBucket(0, $rate);
|
251 |
+
}
|
252 |
+
|
253 |
+
$buckets[$class]->add($line->getWeight());
|
254 |
+
}
|
255 |
+
|
256 |
+
$defaultClass = $defaultRate->getId();
|
257 |
+
if (!isset($buckets[$defaultClass])) {
|
258 |
+
$buckets[$defaultClass] = new WbsItemBucket(0, $defaultRate);
|
259 |
+
}
|
260 |
+
}
|
261 |
+
|
262 |
+
$price = 0;
|
263 |
+
foreach ($buckets as $bucket) {
|
264 |
+
$price += $bucket->calculate();
|
265 |
+
}
|
266 |
+
|
267 |
+
$price = $this->priceClamp->clamp($price);
|
268 |
+
|
269 |
+
$this->add_rate(array(
|
270 |
+
'id' => $this->id,
|
271 |
+
'label' => $this->title,
|
272 |
+
'cost' => $price,
|
273 |
+
'taxes' => '',
|
274 |
+
'calc_tax' => 'per_order'
|
275 |
+
));
|
276 |
+
}
|
277 |
+
|
278 |
+
public function admin_options()
|
279 |
+
{
|
280 |
+
static $already = false;
|
281 |
+
|
282 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
283 |
+
if (version_compare(WC_VERSION, '2.6', '>=')) {
|
284 |
+
if (!$already) {
|
285 |
+
$already = true;
|
286 |
+
} else {
|
287 |
+
return;
|
288 |
+
}
|
289 |
+
}
|
290 |
+
|
291 |
+
if (WBS_Upgrader::instance()->removeUpgradeNotices()) {
|
292 |
+
$this->refresh();
|
293 |
+
}
|
294 |
+
|
295 |
+
$manager = WBS_Profile_Manager::instance(true);
|
296 |
+
$profiles = $manager->profiles();
|
297 |
+
$profile = $manager->profile();
|
298 |
+
|
299 |
+
if (!empty($_GET['delete'])) {
|
300 |
+
|
301 |
+
if (isset($profile)) {
|
302 |
+
delete_option($profile->get_wp_option_name());
|
303 |
+
WbsFactory::getRulesOrderStorage()->remove($profile->profile_id);
|
304 |
+
}
|
305 |
+
|
306 |
+
$this->refresh();
|
307 |
+
}
|
308 |
+
|
309 |
+
if (!isset($profile)) {
|
310 |
+
$profile = new self();
|
311 |
+
$profile->_stub = true;
|
312 |
+
$profiles[] = $profile;
|
313 |
+
}
|
314 |
+
|
315 |
+
if ($profile->_stub &&
|
316 |
+
($sourceProfileId = @$_GET['duplicate']) != null &&
|
317 |
+
($sourceProfile = $manager->profile($sourceProfileId)) != null) {
|
318 |
+
|
319 |
+
$duplicate = clone($sourceProfile);
|
320 |
+
$duplicate->id = $profile->id;
|
321 |
+
$duplicate->profile_id = $profile->profile_id;
|
322 |
+
|
323 |
+
$profiles[array_search($profile, $profiles, true)] = $duplicate;
|
324 |
+
$profile = $duplicate;
|
325 |
+
}
|
326 |
+
|
327 |
+
$create_profile_link_html =
|
328 |
+
'<a class="add-new-h2" href="'.esc_html(WbsRuleUrls::create()).'">'.
|
329 |
+
esc_html__('Add New', 'woowbs').
|
330 |
+
'</a>';
|
331 |
+
|
332 |
+
?>
|
333 |
+
<h3><?php esc_html_e('Weight-based shipping', 'woowbs'); ?></h3>
|
334 |
+
<p><?php esc_html_e('Lets you calculate shipping based on total weight of the cart. You can have multiple rules active.', 'woowbs'); ?></p>
|
335 |
+
<?php echo $this->settingsHelper->trsPromotionHtml() ?>
|
336 |
+
|
337 |
+
|
338 |
+
<table class="form-table">
|
339 |
+
|
340 |
+
<tr class="wbs-title">
|
341 |
+
<th colspan="2">
|
342 |
+
<h4><?php esc_html_e('Rules', 'woowbs'); echo $create_profile_link_html; ?></h4>
|
343 |
+
</th>
|
344 |
+
</tr>
|
345 |
+
|
346 |
+
<tr class="wbs-profiles">
|
347 |
+
<td colspan="2">
|
348 |
+
<?php self::listProfiles($profiles); ?>
|
349 |
+
</td>
|
350 |
+
</tr>
|
351 |
+
|
352 |
+
<?php $profile->generate_settings_html(); ?>
|
353 |
+
</table>
|
354 |
+
<?php
|
355 |
+
}
|
356 |
+
|
357 |
+
public function process_admin_options()
|
358 |
+
{
|
359 |
+
$result = parent::process_admin_options();
|
360 |
+
|
361 |
+
$this->safeInit(true);
|
362 |
+
|
363 |
+
$clone = WBS_Profile_Manager::instance()->profile($this->profile_id);
|
364 |
+
if (isset($clone) && $clone !== $this) {
|
365 |
+
$clone->init();
|
366 |
+
}
|
367 |
+
|
368 |
+
if ($result) {
|
369 |
+
WbsWcTools::purgeWoocommerceShippingCache();
|
370 |
+
}
|
371 |
+
|
372 |
+
return $result;
|
373 |
+
}
|
374 |
+
|
375 |
+
public function display_errors()
|
376 |
+
{
|
377 |
+
foreach ($this->errors as $error) {
|
378 |
+
WC_Admin_Settings::add_error($error);
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
public function validate_positive_decimal_field($key)
|
383 |
+
{
|
384 |
+
return max(0, (float)$this->validate('decimal', $key));
|
385 |
+
}
|
386 |
+
|
387 |
+
public function validate_wbs_range_field($key)
|
388 |
+
{
|
389 |
+
return $this->settingsHelper->validateRangeHtml($key);
|
390 |
+
}
|
391 |
+
|
392 |
+
public function validate_wbs_weight_rate_field($key)
|
393 |
+
{
|
394 |
+
return $this->settingsHelper->validateWeightRateHtml($key);
|
395 |
+
}
|
396 |
+
|
397 |
+
public function validate_wbs_custom_field($key)
|
398 |
+
{
|
399 |
+
return $this->validate(@$this->form_fields[$key]['wbs_real_type'], $key);
|
400 |
+
}
|
401 |
+
|
402 |
+
public function validate_shipping_class_rates_field($key)
|
403 |
+
{
|
404 |
+
return $this->settingsHelper->validateShippingClasses($key);
|
405 |
+
}
|
406 |
+
|
407 |
+
public function generate_positive_decimal_html($key, $data)
|
408 |
+
{
|
409 |
+
return $this->generate_decimal_html($key, $data);
|
410 |
+
}
|
411 |
+
|
412 |
+
public function generate_wbs_range_html($key, $data)
|
413 |
+
{
|
414 |
+
return $this->settingsHelper->generateRangeHtml($key, $data);
|
415 |
+
}
|
416 |
+
|
417 |
+
public function generate_wbs_weight_rate_html($key, $data)
|
418 |
+
{
|
419 |
+
return $this->settingsHelper->generateWeightRateHtml($key, $data);
|
420 |
+
}
|
421 |
+
|
422 |
+
public function generate_wbs_custom_html($key, $data)
|
423 |
+
{
|
424 |
+
$realType = @$data['wbs_real_type'];
|
425 |
+
$data['type'] = $realType;
|
426 |
+
unset($data['wbs_real_type']);
|
427 |
+
|
428 |
+
$rowClass = @$data['wbs_row_class'];
|
429 |
+
unset($data['wbs_row_class']);
|
430 |
+
|
431 |
+
$generator = 'generate_text_html';
|
432 |
+
if ($realType) {
|
433 |
+
$realTypeGenerator = "generate_{$realType}_html";
|
434 |
+
if (method_exists($this, $realTypeGenerator)) {
|
435 |
+
$generator = $realTypeGenerator;
|
436 |
+
}
|
437 |
+
}
|
438 |
+
|
439 |
+
$html = $this->{$generator}($key, $data);
|
440 |
+
|
441 |
+
if ($rowClass) {
|
442 |
+
$html = preg_replace('/\<tr(.*?)(?:class="(.*?)")?(.*?)>/i', '<tr $1 class="$2 '.esc_html($rowClass).'" $3>', $html, 1);
|
443 |
+
}
|
444 |
+
|
445 |
+
return $html;
|
446 |
+
}
|
447 |
+
|
448 |
+
public function generate_shipping_class_rates_html($key, $data)
|
449 |
+
{
|
450 |
+
return $this->settingsHelper->generateShippingClassesHtml($key, $data);
|
451 |
+
}
|
452 |
+
|
453 |
+
public function get_description_html($data)
|
454 |
+
{
|
455 |
+
return parent::get_description_html($data) . @$data['html'];
|
456 |
+
}
|
457 |
+
|
458 |
+
public function get_wp_option_name()
|
459 |
+
{
|
460 |
+
return WBS_Profile_Manager::getRuleSettingsOptionName($this->id, $this->plugin_id);
|
461 |
+
}
|
462 |
+
|
463 |
+
public function getPostKey($key)
|
464 |
+
{
|
465 |
+
return method_exists($this, 'get_field_key')
|
466 |
+
? $this->get_field_key($key)
|
467 |
+
: "{$this->plugin_id}{$this->id}_{$key}";
|
468 |
+
}
|
469 |
+
|
470 |
+
|
471 |
+
private $settingsHelper;
|
472 |
+
|
473 |
+
private function safeInit($showMessage = false)
|
474 |
+
{
|
475 |
+
try {
|
476 |
+
|
477 |
+
$this->init();
|
478 |
+
$this->valid = true;
|
479 |
+
|
480 |
+
} catch (Exception $e) {
|
481 |
+
|
482 |
+
$this->valid = false;
|
483 |
+
$this->enabled = 'no';
|
484 |
+
|
485 |
+
if ($showMessage) {
|
486 |
+
WC_Admin_Settings::add_error(
|
487 |
+
"Shipping rule '{$this->name}' has been deactivated due to an error. Double-check its settings and fix errors to make it active.
|
488 |
+
Unerlying error: \"{$e->getMessage()}\" at {$e->getFile()}:{$e->getLine()}."
|
489 |
+
);
|
490 |
+
}
|
491 |
+
}
|
492 |
+
}
|
493 |
+
|
494 |
+
private function init()
|
495 |
+
{
|
496 |
+
$this->init_form_fields();
|
497 |
+
$this->init_settings();
|
498 |
+
|
499 |
+
$this->enabled = $this->get_option('enabled');
|
500 |
+
$this->name = $this->get_option('name');
|
501 |
+
$this->title = $this->get_option('title');
|
502 |
+
$this->{'type'} = 'order';
|
503 |
+
$this->tax_status = $this->get_option('tax_status');
|
504 |
+
|
505 |
+
$this->availability = $this->get_option('availability');
|
506 |
+
$this->countries = $this->get_option('countries');
|
507 |
+
$this->weight = $this->getRangeOption('weight');
|
508 |
+
$this->subtotal = $this->getRangeOption('subtotal');
|
509 |
+
$this->subtotalWithTax = $this->get_option('subtotal_with_tax') === 'yes';
|
510 |
+
|
511 |
+
$this->fee = (float)$this->get_option('fee');
|
512 |
+
$this->settings['fee'] = $this->formatFloat($this->fee);
|
513 |
+
|
514 |
+
$this->weightRate = WbsProgressiveRate::fromArray($this->get_option('weight_rate', array()));
|
515 |
+
|
516 |
+
if (empty($this->countries)) {
|
517 |
+
$this->availability = $this->settings['availability'] = 'all';
|
518 |
+
}
|
519 |
+
|
520 |
+
$this->shippingClassRates = $this->get_option('shipping_class_rates', new WbsBucketRates());
|
521 |
+
|
522 |
+
$this->priceClamp = $this->getRangeOption('price_clamp');
|
523 |
+
}
|
524 |
+
|
525 |
+
private function formatFloat($value, $zeroReplacement = '')
|
526 |
+
{
|
527 |
+
if ($value == 0) {
|
528 |
+
return $zeroReplacement;
|
529 |
+
}
|
530 |
+
|
531 |
+
return wc_float_to_string($value);
|
532 |
+
}
|
533 |
+
|
534 |
+
private function makeCostString()
|
535 |
+
{
|
536 |
+
$baseCost = $this->fee ? wc_format_localized_price($this->fee) : null;
|
537 |
+
|
538 |
+
$weightRate = null;
|
539 |
+
if ($cost = $this->weightRate->getCost()) {
|
540 |
+
|
541 |
+
$weightRate .= wc_format_localized_price($cost);
|
542 |
+
|
543 |
+
$weightUnit = get_option('woocommerce_weight_unit');
|
544 |
+
|
545 |
+
$step = $this->weightRate->getStep();
|
546 |
+
$weightRate = sprintf(__('%s per %s %s', 'woowbs'), $weightRate, $step ? wc_format_localized_decimal($step) : null, $weightUnit);
|
547 |
+
|
548 |
+
if ($skip = $this->weightRate->getSkip()) {
|
549 |
+
$weightRate = sprintf(__('%s (from %s %s)', 'woowbs'), $weightRate, $skip, $weightUnit);
|
550 |
+
}
|
551 |
+
}
|
552 |
+
|
553 |
+
$cost = null;
|
554 |
+
if ($baseCost && $weightRate) {
|
555 |
+
$cost = sprintf(__('%s + %s'), $baseCost, $weightRate);
|
556 |
+
} else if ($baseCost || $weightRate) {
|
557 |
+
$cost = $baseCost . $weightRate;
|
558 |
+
} else {
|
559 |
+
$cost = __('Free', 'woowbs');
|
560 |
+
}
|
561 |
+
|
562 |
+
return $cost;
|
563 |
+
}
|
564 |
+
|
565 |
+
private function refresh()
|
566 |
+
{
|
567 |
+
echo '<script>location.href = ', json_encode(WbsRuleUrls::generic()), ';</script>';
|
568 |
+
die();
|
569 |
+
}
|
570 |
+
|
571 |
+
private function getRangeOption($name)
|
572 |
+
{
|
573 |
+
return WbsRange::fromArray($this->get_option($name, array()));
|
574 |
+
}
|
575 |
+
|
576 |
+
private function validate($type, $key)
|
577 |
+
{
|
578 |
+
$result = null;
|
579 |
+
|
580 |
+
$method = "validate_{$type}_field";
|
581 |
+
if (!$type || !method_exists($this, $method)) {
|
582 |
+
$method = 'validate_text_field';
|
583 |
+
}
|
584 |
+
|
585 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
586 |
+
if (version_compare(WC_VERSION, '2.6', '<')) {
|
587 |
+
$result = $this->$method($key);
|
588 |
+
} else {
|
589 |
+
$result = $this->$method($key, @$_POST[$this->getPostKey($key)]);
|
590 |
+
}
|
591 |
+
|
592 |
+
return $result;
|
593 |
+
}
|
594 |
+
|
595 |
+
private static function listProfiles(array $profiles)
|
596 |
+
{
|
597 |
+
$current_profile_id = WBS_Profile_Manager::instance()->current_profile_id();
|
598 |
+
|
599 |
+
?>
|
600 |
+
<table id="woowbs_shipping_methods" class="wc_shipping widefat">
|
601 |
+
<thead>
|
602 |
+
<tr>
|
603 |
+
<th class="sort"><i class="spinner"></i></th>
|
604 |
+
<th class="name"> <?php esc_html_e('Name', 'woowbs'); ?> </th>
|
605 |
+
<th> <?php esc_html_e('Destination', 'woowbs'); ?> </th>
|
606 |
+
<th> <?php esc_html_e('Weight', 'woowbs'); ?> </th>
|
607 |
+
<th> <?php esc_html_e('Subtotal', 'woowbs'); ?> </th>
|
608 |
+
<th> <?php esc_html_e('Cost', 'woowbs'); ?> </th>
|
609 |
+
<th class="status"> <?php esc_html_e('Active', 'woowbs'); ?> </th>
|
610 |
+
<th> <?php esc_html_e('Actions'); ?> </th>
|
611 |
+
</tr>
|
612 |
+
</thead>
|
613 |
+
<tbody>
|
614 |
+
<?php /** @var WC_Weight_Based_Shipping[] $profiles */ ?>
|
615 |
+
<?php foreach ($profiles as $profile): ?>
|
616 |
+
<tr
|
617 |
+
class="<?php echo ($profile->profile_id === $current_profile_id ? 'wbs-current' : null) ?>"
|
618 |
+
data-settings-url="<?php echo esc_html(WbsRuleUrls::edit($profile)) ?>"
|
619 |
+
data-profile-id="<?php echo esc_html($profile->id) ?>"
|
620 |
+
>
|
621 |
+
<td class="sort"></td>
|
622 |
+
|
623 |
+
<td class="name"><?php echo esc_html($profile->name)?></td>
|
624 |
+
|
625 |
+
<?php if ($profile->valid): ?>
|
626 |
+
<td class="countries">
|
627 |
+
<?php if ($profile->availability === 'all'): ?>
|
628 |
+
<?php esc_html_e('Any', 'woowbs') ?>
|
629 |
+
<?php else: ?>
|
630 |
+
<?php if ($profile->availability === 'excluding'): ?>
|
631 |
+
<?php esc_html_e('All except', 'woowbs') ?>
|
632 |
+
<?php endif; ?>
|
633 |
+
<?php echo esc_html(join(', ', $profile->countries))?>
|
634 |
+
<?php endif; ?>
|
635 |
+
</td>
|
636 |
+
|
637 |
+
<?php foreach (array($profile->weight, $profile->subtotal) as $range): ?>
|
638 |
+
<td>
|
639 |
+
<?php
|
640 |
+
echo
|
641 |
+
isset($range->min) || isset($range->max)
|
642 |
+
?
|
643 |
+
($range->minInclusive || !isset($range->min) ? '[' : '(') .
|
644 |
+
esc_html(wc_format_localized_decimal((float)$range->min)) .
|
645 |
+
' – ' .
|
646 |
+
(isset($range->max) ? esc_html(wc_format_localized_decimal($range->max)) : '<span style="font-family:monospace">∞</span>') .
|
647 |
+
($range->maxInclusive ? ']' : ')')
|
648 |
+
:
|
649 |
+
'Any';
|
650 |
+
?>
|
651 |
+
</td>
|
652 |
+
<?php endforeach; ?>
|
653 |
+
|
654 |
+
<td>
|
655 |
+
<?php echo esc_html($profile->makeCostString()); ?>
|
656 |
+
</td>
|
657 |
+
<?php else: ?>
|
658 |
+
<td colspan="4" align="center">
|
659 |
+
<?php esc_html_e('Invalid state', 'woowbs') ?>
|
660 |
+
</td>
|
661 |
+
<?php endif; ?>
|
662 |
+
|
663 |
+
<td class="status">
|
664 |
+
<?php if ($profile->enabled == 'yes'): ?>
|
665 |
+
<span class="status-enabled tips" data-tip="<?php esc_html_e('Enabled', 'woowbs')?>"><?php esc_html_e('Enabled', 'woowbs')?></span>
|
666 |
+
<?php else: ?>
|
667 |
+
-
|
668 |
+
<?php endif; ?>
|
669 |
+
</td>
|
670 |
+
|
671 |
+
<td class="actions">
|
672 |
+
<a class="button" href="<?php echo esc_html(WbsRuleUrls::duplicate($profile)) ?>">
|
673 |
+
<?php esc_html_e('Duplicate', 'woowbs') ?>
|
674 |
+
</a>
|
675 |
+
|
676 |
+
<a class="button" href="<?php echo esc_html(WbsRuleUrls::delete($profile)) ?>"
|
677 |
+
onclick="return confirm('<?php esc_html_e('Are you sure you want to delete this rule?', 'woowbs') ?>');">
|
678 |
+
<?php esc_html_e('Delete') ?>
|
679 |
+
</a>
|
680 |
+
</td>
|
681 |
+
</tr>
|
682 |
+
<?php endforeach; ?>
|
683 |
+
</tbody>
|
684 |
+
</table>
|
685 |
+
|
686 |
+
<!--suppress CssUnusedSymbol -->
|
687 |
+
<style>
|
688 |
+
#woowbs_shipping_methods td { cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
689 |
+
#woowbs_shipping_methods .sort { width: 1em; }
|
690 |
+
#woowbs_shipping_methods td.sort { cursor: move; }
|
691 |
+
#woowbs_shipping_methods th.sort { padding: 0; }
|
692 |
+
#woowbs_shipping_methods .actions { white-space: nowrap; }
|
693 |
+
#woowbs_shipping_methods .countries { max-width: 15em; }
|
694 |
+
#woowbs_shipping_methods .wbs-current td { background-color: #eee; }
|
695 |
+
#woowbs_shipping_methods tr:hover td { background-color: #ddd; }
|
696 |
+
#woowbs_shipping_methods .spinner { display: none; visibility: visible; margin: 0; width: 17px; height: 17px; background-size: 17px 17px; }
|
697 |
+
#woowbs_shipping_methods.in-progress .spinner { display: block; }
|
698 |
+
tr.wbs-title th { padding: 2em 0 0 0; }
|
699 |
+
tr.wbs-title h4 { font-size: 1.2em; }
|
700 |
+
.wc-settings-sub-title { padding-top: 2em; }
|
701 |
+
.form-table { border-top: 1px solid #aaa; }
|
702 |
+
tr.wbs-profiles > td { padding: 0; }
|
703 |
+
|
704 |
+
.wbs-destination label { display: none; }
|
705 |
+
.wbs-destination .forminp { padding-top: 0; }
|
706 |
+
.wbs-destination fieldset { margin-top: -15px !important; }
|
707 |
+
|
708 |
+
.wbs-subtotal .forminp { padding-bottom: 0}
|
709 |
+
.wbs-subtotal + tr > * { padding-top: 0 }
|
710 |
+
.wbs-subtotal + tr label { display: none; }
|
711 |
+
.wbs-minifield { width: 15.7em; }
|
712 |
+
.wbs-minifield.wc_input_decimal { text-align: right; }
|
713 |
+
.wbs-minifield-container { display: block ! important; }
|
714 |
+
.wbs-minifield-label { display: inline-block; min-width: 3em; }
|
715 |
+
.wbs-range-simple .wbs-minifield-label { min-width: 5em; }
|
716 |
+
.wbs-range-simple .wbs-minifield { min-width: 19.7em; }
|
717 |
+
.wbs-weight-rate .wbs-minifield-label { min-width: 5em; }
|
718 |
+
.wbs-weight-rate .wbs-minifield { width: 17.3em; }
|
719 |
+
|
720 |
+
.wbs-input-group {
|
721 |
+
display: inline-block;
|
722 |
+
height: 29px;
|
723 |
+
box-sizing: border-box;
|
724 |
+
}
|
725 |
+
|
726 |
+
.wbs-input-group-addon {
|
727 |
+
display: inline-block;
|
728 |
+
box-sizing: border-box;
|
729 |
+
height: 100%;
|
730 |
+
width: 2.5em;
|
731 |
+
text-align: center;
|
732 |
+
border: 1px solid #ddd;
|
733 |
+
padding: 3px 0;
|
734 |
+
}
|
735 |
+
|
736 |
+
.wbs-input-group-addon:first-child {
|
737 |
+
border-right: 0;
|
738 |
+
float: left;
|
739 |
+
}
|
740 |
+
|
741 |
+
.wbs-input-group-addon:last-child {
|
742 |
+
border-left: 0;
|
743 |
+
float: right;
|
744 |
+
}
|
745 |
+
|
746 |
+
.wbs-input-group input[type="text"] {
|
747 |
+
display: inline-block;
|
748 |
+
height: 100%;
|
749 |
+
box-sizing: border-box;
|
750 |
+
margin: 0;
|
751 |
+
}
|
752 |
+
|
753 |
+
.wbs-code {
|
754 |
+
font-size: inherit;
|
755 |
+
padding: 0 0.5em;
|
756 |
+
font-family: monospace;
|
757 |
+
}
|
758 |
+
|
759 |
+
.shippingrows {
|
760 |
+
overflow: hidden;
|
761 |
+
}
|
762 |
+
|
763 |
+
.shippingrows th, .shippingrows td {
|
764 |
+
width: auto;
|
765 |
+
white-space: nowrap;
|
766 |
+
padding: 1em;
|
767 |
+
}
|
768 |
+
|
769 |
+
.shippingrows .wc_input_decimal {
|
770 |
+
width: 7em;
|
771 |
+
}
|
772 |
+
|
773 |
+
.flat_rate .wbs-minifield-container {
|
774 |
+
display: inline !important;
|
775 |
+
margin-left: 1em;
|
776 |
+
}
|
777 |
+
|
778 |
+
.flat_rate .wbs-minifield-container:first-child {
|
779 |
+
margin-left: 0;
|
780 |
+
}
|
781 |
+
|
782 |
+
.flat_rate .wbs-minifield-label {
|
783 |
+
display: inline;
|
784 |
+
}
|
785 |
+
|
786 |
+
.flat_rate .wbs-minifield {
|
787 |
+
width: 6em;
|
788 |
+
}
|
789 |
+
|
790 |
+
.flat_rate_tpl {
|
791 |
+
display: none;
|
792 |
+
}
|
793 |
+
</style>
|
794 |
+
<?php
|
795 |
+
}
|
796 |
+
}
|
797 |
+
?>
|
WbsFactory.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WbsFactory
|
3 |
+
{
|
4 |
+
public static function getRulesOrderStorage()
|
5 |
+
{
|
6 |
+
if (!isset(self::$rulesOrderStorage)) {
|
7 |
+
self::$rulesOrderStorage = new WbsRulesOrderStorage(WC_Weight_Based_Shipping::PLUGIN_PREFIX.'rules_order');
|
8 |
+
}
|
9 |
+
|
10 |
+
return self::$rulesOrderStorage;
|
11 |
+
}
|
12 |
+
|
13 |
+
private static $rulesOrderStorage;
|
14 |
+
}
|
WbsRuleUrls.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WbsRuleUrls
|
3 |
+
{
|
4 |
+
public static function generic($parameters = array())
|
5 |
+
{
|
6 |
+
$query = build_query(self::arrayFilterNull($parameters + array(
|
7 |
+
"page" => (version_compare(WC()->version, '2.1', '>=') ? "wc-settings" : "woocommerce_settings"),
|
8 |
+
"tab" => "shipping",
|
9 |
+
"section" => "wc_weight_based_shipping",
|
10 |
+
)));
|
11 |
+
|
12 |
+
$url = admin_url("admin.php?{$query}");
|
13 |
+
|
14 |
+
return $url;
|
15 |
+
}
|
16 |
+
|
17 |
+
public static function create(array $additionals = array())
|
18 |
+
{
|
19 |
+
return self::genericWithProfile(WBS_Profile_Manager::instance()->new_profile_id(), $additionals);
|
20 |
+
}
|
21 |
+
|
22 |
+
public static function edit(WC_Weight_Based_Shipping $rule, array $parameters = array())
|
23 |
+
{
|
24 |
+
return self::genericWithProfile($rule->profile_id, $parameters);
|
25 |
+
}
|
26 |
+
|
27 |
+
public static function duplicate(WC_Weight_Based_Shipping $rule)
|
28 |
+
{
|
29 |
+
return self::create(array('duplicate' => $rule->profile_id));
|
30 |
+
}
|
31 |
+
|
32 |
+
public static function delete(WC_Weight_Based_Shipping $rule)
|
33 |
+
{
|
34 |
+
return self::edit($rule, array('delete' => 'yes'));
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
private static function genericWithProfile($profileId, array $parameters = array())
|
39 |
+
{
|
40 |
+
$parameters['wbs_profile'] = $profileId;
|
41 |
+
$url = self::generic($parameters);
|
42 |
+
return $url;
|
43 |
+
}
|
44 |
+
|
45 |
+
public static function arrayFilterNull($array)
|
46 |
+
{
|
47 |
+
foreach ($array as $key => $value) {
|
48 |
+
if ($value === null) {
|
49 |
+
unset($array[$key]);
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
return $array;
|
54 |
+
}
|
55 |
+
}
|
WbsRulesOrderStorage.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WbsRulesOrderStorage
|
3 |
+
{
|
4 |
+
public function __construct($storageKeyName)
|
5 |
+
{
|
6 |
+
$this->storageKeyName = $storageKeyName;
|
7 |
+
}
|
8 |
+
|
9 |
+
public function sort(array $profiles)
|
10 |
+
{
|
11 |
+
$profilesWithDefinedOrder = array();
|
12 |
+
$profilesWithNoDefineOrder = array();
|
13 |
+
|
14 |
+
$weights = $this->getProfilesSortWeights();
|
15 |
+
foreach ($profiles as $profile) {
|
16 |
+
if (isset($weights[$profile])) {
|
17 |
+
$profilesWithDefinedOrder[$weights[$profile]] = $profile;
|
18 |
+
} else {
|
19 |
+
$profilesWithNoDefineOrder[] = $profile;
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
ksort($profilesWithDefinedOrder);
|
24 |
+
|
25 |
+
$sortedProfiles = array_merge($profilesWithDefinedOrder, $profilesWithNoDefineOrder);
|
26 |
+
|
27 |
+
return $sortedProfiles;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function add($profile)
|
31 |
+
{
|
32 |
+
$weights = $this->getProfilesSortWeights();
|
33 |
+
$weights[$profile] = max($weights)+1;
|
34 |
+
$this->setProfileSortWeights($weights);
|
35 |
+
}
|
36 |
+
|
37 |
+
public function remove($profile)
|
38 |
+
{
|
39 |
+
$weights = $this->getProfilesSortWeights();
|
40 |
+
unset($weights[$profile]);
|
41 |
+
$this->setProfileSortWeights($weights);
|
42 |
+
}
|
43 |
+
|
44 |
+
public function set(array $profiles)
|
45 |
+
{
|
46 |
+
$this->setProfileSortWeights(array_flip(array_values($profiles)));
|
47 |
+
}
|
48 |
+
|
49 |
+
private $storageKeyName;
|
50 |
+
|
51 |
+
private function setProfileSortWeights(array $profileWeights)
|
52 |
+
{
|
53 |
+
update_option($this->storageKeyName, $profileWeights);
|
54 |
+
}
|
55 |
+
|
56 |
+
private function getProfilesSortWeights()
|
57 |
+
{
|
58 |
+
return get_option($this->storageKeyName, array());
|
59 |
+
}
|
60 |
+
}
|
WbsSettingsHtmlTools.php
ADDED
@@ -0,0 +1,483 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WbsSettingsHtmlTools
|
3 |
+
{
|
4 |
+
public function __construct(WC_Weight_Based_Shipping $settings)
|
5 |
+
{
|
6 |
+
$this->settings = $settings;
|
7 |
+
}
|
8 |
+
|
9 |
+
public function generateRangeHtml($key, array $data = array())
|
10 |
+
{
|
11 |
+
$field = $this->settings->getPostKey($key);
|
12 |
+
|
13 |
+
$range = $this->settings->get_option($key);
|
14 |
+
if ($range === '' || $range === false) {
|
15 |
+
$range = null;
|
16 |
+
}
|
17 |
+
|
18 |
+
$data['wbs_range_type'] = @$data['wbs_range_type'] !== 'simple' ? 'default' : $data['wbs_range_type'];
|
19 |
+
$simple = @$data['wbs_range_type'] == 'simple';
|
20 |
+
|
21 |
+
return $this->formRow('
|
22 |
+
<label class="wbs-minifield-container">
|
23 |
+
<span class="wbs-minifield-label">' . ($simple ? 'minimum' : 'above') . '</span>
|
24 |
+
' . $this->rangeInput('min', @$range['min'], true, $simple, $field) . '
|
25 |
+
</label>
|
26 |
+
<label class="wbs-minifield-container">
|
27 |
+
<span class="wbs-minifield-label">' . ($simple ? 'maximum' : 'below') . '</span>
|
28 |
+
' . $this->rangeInput('max', @$range['max'], false, $simple, $field) . '
|
29 |
+
</label>
|
30 |
+
',
|
31 |
+
"{$field}_min",
|
32 |
+
array('wbs-range', "wbs-range-{$data['wbs_range_type']}"),
|
33 |
+
$data
|
34 |
+
);
|
35 |
+
}
|
36 |
+
|
37 |
+
public function validateRangeHtml($key)
|
38 |
+
{
|
39 |
+
$range = array();
|
40 |
+
|
41 |
+
$input = @$_POST[$this->settings->getPostKey($key)];
|
42 |
+
foreach(array('min', 'max') as $limit) {
|
43 |
+
$range[$limit]['value'] = $this->receiveDecimal(@$input[$limit]['value']);
|
44 |
+
$range[$limit]['inclusive'] = (bool)(int)@$input[$limit]['inclusive'];
|
45 |
+
}
|
46 |
+
|
47 |
+
if (isset($range['min']['value']) && isset($range['max']['value'])) {
|
48 |
+
if ($range['min']['value'] > $range['max']['value']) {
|
49 |
+
$tmp = $range['max']['value'];
|
50 |
+
$range['max']['value'] = $range['min']['value'];
|
51 |
+
$range['min']['value'] = $tmp;
|
52 |
+
} else if ($range['min']['value'] === $range['max']['value']) {
|
53 |
+
$range['min']['inclusive'] = $range['max']['inclusive'] = true;
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
return $range;
|
58 |
+
}
|
59 |
+
|
60 |
+
public function generateWeightRateHtml($key, array $data = array())
|
61 |
+
{
|
62 |
+
$inputNamePrefix = $this->settings->getPostKey($key);
|
63 |
+
$id = "{$inputNamePrefix}_cost";
|
64 |
+
$value = $this->settings->get_option($key);
|
65 |
+
|
66 |
+
return $this->formRow(
|
67 |
+
$this->weightRate($inputNamePrefix, $value),
|
68 |
+
$id, 'wbs-weight-rate', $data
|
69 |
+
);
|
70 |
+
}
|
71 |
+
|
72 |
+
public function validateWeightRateHtml($key)
|
73 |
+
{
|
74 |
+
return $this->receiveWeightRate(@$_POST[$this->settings->getPostKey($key)]);
|
75 |
+
}
|
76 |
+
|
77 |
+
public function generateShippingClassesHtml($key, $data)
|
78 |
+
{
|
79 |
+
$prefix = $this->settings->getPostKey($key);
|
80 |
+
|
81 |
+
$data = wp_parse_args($data, array(
|
82 |
+
'title' => '',
|
83 |
+
'desc_tip' => '',
|
84 |
+
'description' => '',
|
85 |
+
));
|
86 |
+
|
87 |
+
$rates = $this->settings->get_option($key);
|
88 |
+
if (!$rates) {
|
89 |
+
$rates = new WbsBucketRates();
|
90 |
+
}
|
91 |
+
|
92 |
+
if (!$rates->listAll()) {
|
93 |
+
ob_start();
|
94 |
+
?>
|
95 |
+
<tr valign="top">
|
96 |
+
<th scope="row" class="titledesc">
|
97 |
+
<?php echo wp_kses_post($data['title']); ?>
|
98 |
+
<?php echo $this->settings->get_description_html($data); ?>
|
99 |
+
</th>
|
100 |
+
<td>
|
101 |
+
<?php echo self::premiumPromotionHtml() ?>
|
102 |
+
</td>
|
103 |
+
</tr>
|
104 |
+
<?php
|
105 |
+
return ob_get_clean();
|
106 |
+
}
|
107 |
+
|
108 |
+
$tableId = "{$this->settings->id}_flat_rates";
|
109 |
+
|
110 |
+
ob_start();
|
111 |
+
?>
|
112 |
+
<tr valign="top">
|
113 |
+
<th scope="row" class="titledesc">
|
114 |
+
<?php echo wp_kses_post($data['title']); ?>
|
115 |
+
<?php echo $this->settings->get_description_html($data); ?>
|
116 |
+
</th>
|
117 |
+
<td class="forminp" id="<?php echo esc_html($tableId); ?>">
|
118 |
+
<table class="shippingrows widefat" cellspacing="0">
|
119 |
+
<thead>
|
120 |
+
<tr>
|
121 |
+
<th class="check-column"><input type="checkbox"></th>
|
122 |
+
<th class="shipping_class"><?php _e('Shipping Class', 'woowbs'); ?></th>
|
123 |
+
<th><?php _e('Additional Cost', 'woowbs'); ?></th>
|
124 |
+
<th><?php _e('Weight Rate', 'woowbs'); ?></th>
|
125 |
+
</tr>
|
126 |
+
</thead>
|
127 |
+
<tbody class="flat_rates">
|
128 |
+
<?php
|
129 |
+
foreach (array_values($rates->listAll()) as $i => $rate) {
|
130 |
+
echo $this->shippingClassRateRow($prefix, $i, $rate);
|
131 |
+
}
|
132 |
+
|
133 |
+
echo $this->shippingClassRateRow($prefix, '{{{rate_id}}}', null, 'flat_rate_tpl');
|
134 |
+
?>
|
135 |
+
</tbody>
|
136 |
+
<tfoot>
|
137 |
+
<tr>
|
138 |
+
<th colspan="5">
|
139 |
+
<a href="#" class="add button"><?php _e('Add', 'woowbs'); ?></a>
|
140 |
+
<a href="#" class="remove button"><?php _e('Delete selected costs', 'woowbs'); ?></a>
|
141 |
+
</th>
|
142 |
+
</tr>
|
143 |
+
</tfoot>
|
144 |
+
</table>
|
145 |
+
<script type="text/javascript">
|
146 |
+
jQuery(function($) {
|
147 |
+
|
148 |
+
var $table = $("#<?php echo $tableId ?>");
|
149 |
+
var $templateRow = $table.find('.flat_rate_tpl');
|
150 |
+
|
151 |
+
$table
|
152 |
+
|
153 |
+
.on('click', '.add', function() {
|
154 |
+
|
155 |
+
var rateCount = $table.find('.flat_rate').size();
|
156 |
+
var newRateHtml = $('<div/>').append($templateRow.clone()).html().replace(/\{\{\{rate_id}}}/g, rateCount);
|
157 |
+
$(newRateHtml).insertBefore($templateRow).removeClass('flat_rate_tpl');
|
158 |
+
|
159 |
+
return false;
|
160 |
+
})
|
161 |
+
|
162 |
+
.on('click', '.remove', function() {
|
163 |
+
|
164 |
+
var answer = confirm("<?php _e('Delete the selected rates?', 'woowbs'); ?>");
|
165 |
+
|
166 |
+
if (answer) {
|
167 |
+
$table.find('.check-column input:checked').each(function(i, el) {
|
168 |
+
$(el).closest('.flat_rate:not(.flat_rate_tpl)').remove();
|
169 |
+
});
|
170 |
+
}
|
171 |
+
|
172 |
+
return false;
|
173 |
+
})
|
174 |
+
|
175 |
+
.closest('form').on('submit', function() {
|
176 |
+
$templateRow.remove();
|
177 |
+
})
|
178 |
+
;
|
179 |
+
});
|
180 |
+
</script>
|
181 |
+
</td>
|
182 |
+
</tr>
|
183 |
+
<?php
|
184 |
+
return ob_get_clean();
|
185 |
+
}
|
186 |
+
|
187 |
+
public function validateShippingClasses($key)
|
188 |
+
{
|
189 |
+
$rates = new WbsBucketRates();
|
190 |
+
|
191 |
+
$rows = (array)@$_POST[$this->settings->getPostKey($key)];
|
192 |
+
foreach ($rows as $i => $row) {
|
193 |
+
$rates->add(new WbsBucketRate(
|
194 |
+
@$row['class'],
|
195 |
+
$this->receiveDecimal(@$row['fee']),
|
196 |
+
WbsProgressiveRate::fromArray($this->receiveWeightRate(@$row['weight_rate']))
|
197 |
+
));
|
198 |
+
}
|
199 |
+
|
200 |
+
return $rates;
|
201 |
+
}
|
202 |
+
|
203 |
+
public function premiumPromotionHtml($feature = 'The function')
|
204 |
+
{
|
205 |
+
return '
|
206 |
+
<p>
|
207 |
+
'.esc_html($feature).' is available in the
|
208 |
+
<a href="https://codecanyon.net/item/woocommerce-weight-based-shipping/10099013?ref=dangoodman" target="_blank">Plus version</a>.
|
209 |
+
Try out a <a href="https://codecanyon.net/item/woocommerce-weight-based-shipping/full_screen_preview/10099013?ref=dangoodman" target="_blank">live demo</a>.
|
210 |
+
</p>';
|
211 |
+
}
|
212 |
+
|
213 |
+
public function trsPromotionHtml()
|
214 |
+
{
|
215 |
+
return '
|
216 |
+
<p>
|
217 |
+
In case you need a more flexible shipping solution take a look at our <a href="http://tablerateshipping.com/" target="_blank">advanced shipping plugin</a>.
|
218 |
+
</p>
|
219 |
+
';
|
220 |
+
}
|
221 |
+
|
222 |
+
private $settings;
|
223 |
+
|
224 |
+
private function shippingClassSelect($name, $value = null)
|
225 |
+
{
|
226 |
+
$html = '<select name="' . esc_attr($name) . '" class="select">';
|
227 |
+
|
228 |
+
if ($classes = WC()->shipping->get_shipping_classes()) {
|
229 |
+
foreach ($classes as $shipping_class) {
|
230 |
+
$html .=
|
231 |
+
'<option value="' . esc_attr($shipping_class->slug) . '" ' . selected($shipping_class->slug, $value, false) . '>' .
|
232 |
+
$shipping_class->name .
|
233 |
+
'</option>';
|
234 |
+
}
|
235 |
+
} else {
|
236 |
+
$html .= '<option value="">' . __('Select a class…', 'woowbs') . '</option>';
|
237 |
+
}
|
238 |
+
|
239 |
+
return $html;
|
240 |
+
}
|
241 |
+
|
242 |
+
private function shippingClassRateRow($inputNamePrefix, $rateId, WbsBucketRate $rate = null, $class = null)
|
243 |
+
{
|
244 |
+
return '
|
245 |
+
<tr class="flat_rate ' . esc_html($class) . '">
|
246 |
+
<th class="check-column">
|
247 |
+
<input type="checkbox" name="select" />
|
248 |
+
</th>
|
249 |
+
<td class="flat_rate_class">
|
250 |
+
' . $this->shippingClassSelect(
|
251 |
+
"{$inputNamePrefix}[{$rateId}][class]",
|
252 |
+
$rate ? $rate->getId() : null
|
253 |
+
) . '
|
254 |
+
</td>
|
255 |
+
<td>' .
|
256 |
+
$this->decimalInput(array(
|
257 |
+
'value' => $rate ? $rate->getFlatRate() : null,
|
258 |
+
'name' => "{$inputNamePrefix}[{$rateId}][fee]"
|
259 |
+
)) . '
|
260 |
+
</td>
|
261 |
+
<td>' .
|
262 |
+
$this->weightRate(
|
263 |
+
"{$inputNamePrefix}[{$rateId}][weight_rate]",
|
264 |
+
$rate ? $rate->getProgressiveRate()->toArray() : null,
|
265 |
+
false
|
266 |
+
) . '
|
267 |
+
</td>
|
268 |
+
</tr>
|
269 |
+
';
|
270 |
+
}
|
271 |
+
|
272 |
+
private function weightRate($inputNamePrefix, array $value = null, $placeholders = true)
|
273 |
+
{
|
274 |
+
$id = "{$inputNamePrefix}_cost";
|
275 |
+
|
276 |
+
$weightUnit = get_option('woocommerce_weight_unit');
|
277 |
+
|
278 |
+
$fields = array(
|
279 |
+
array(
|
280 |
+
'id' => $id,
|
281 |
+
'name' => 'cost',
|
282 |
+
'label' => 'charge',
|
283 |
+
'placeholder' => sprintf(__('e.g. %s'), strip_tags(wc_price(2.5))),
|
284 |
+
'decorator' => get_woocommerce_currency_symbol(),
|
285 |
+
'decorator_left' => substr(get_option('woocommerce_currency_pos'), 0, 1) === 'l',
|
286 |
+
),
|
287 |
+
array(
|
288 |
+
'id' => null,
|
289 |
+
'name' => 'step',
|
290 |
+
'label' => 'per each',
|
291 |
+
'placeholder' => sprintf(__('e.g. %s %s'), wc_format_localized_decimal(0.5), $weightUnit),
|
292 |
+
'decorator' => $weightUnit,
|
293 |
+
'decorator_left' => false,
|
294 |
+
),
|
295 |
+
array(
|
296 |
+
'id' => null,
|
297 |
+
'name' => 'skip',
|
298 |
+
'label' => 'over',
|
299 |
+
'placeholder' => sprintf(__('e.g. %s %s'), wc_format_localized_decimal(3), $weightUnit),
|
300 |
+
'decorator' => $weightUnit,
|
301 |
+
'decorator_left' => false,
|
302 |
+
)
|
303 |
+
);
|
304 |
+
|
305 |
+
$html = '';
|
306 |
+
|
307 |
+
foreach ($fields as $field) {
|
308 |
+
|
309 |
+
$decorator = '<span class="wbs-input-group-addon">' . esc_html($field['decorator']) . '</span>';
|
310 |
+
|
311 |
+
$html .= '
|
312 |
+
<label class="wbs-minifield-container">
|
313 |
+
<span class="wbs-minifield-label">' . esc_html($field['label']) . '</span>
|
314 |
+
<div class="wbs-input-group">
|
315 |
+
' . ($field['decorator_left'] ? $decorator : null) . '
|
316 |
+
' . $this->decimalInput(array(
|
317 |
+
'id' => $field['id'],
|
318 |
+
'class' => 'wbs-minifield',
|
319 |
+
'name' => "{$inputNamePrefix}[{$field['name']}]",
|
320 |
+
'value' => (float)($v = @$value[$field['name']]) === 0.0 ? null : $v,
|
321 |
+
'placeholder' => $placeholders ? $field['placeholder'] : null,
|
322 |
+
)) . '
|
323 |
+
' . ($field['decorator_left'] ? null : $decorator) . '
|
324 |
+
</div>
|
325 |
+
</label>
|
326 |
+
';
|
327 |
+
}
|
328 |
+
|
329 |
+
return $html;
|
330 |
+
}
|
331 |
+
|
332 |
+
private function rangeInput($name, $current, $defaultInclusive, $simple, $field)
|
333 |
+
{
|
334 |
+
$html = $this->decimalInput(array(
|
335 |
+
'id' => "{$field}_{$name}",
|
336 |
+
'name' => "{$field}[{$name}][value]",
|
337 |
+
'class' => "wbs-minifield",
|
338 |
+
'value' => @$current['value'],
|
339 |
+
'placeholder' => $simple ? esc_html($name) : null,
|
340 |
+
));
|
341 |
+
|
342 |
+
if (!$simple) {
|
343 |
+
$html .= '
|
344 |
+
<label> ' .
|
345 |
+
$this->input(array(
|
346 |
+
'type' => 'checkbox',
|
347 |
+
'name' =>"{$field}[{$name}][inclusive]",
|
348 |
+
'value' => 1,
|
349 |
+
'checked' => isset($current['inclusive']) ? $current['inclusive'] : $defaultInclusive,
|
350 |
+
)) .
|
351 |
+
' or equal
|
352 |
+
</label>
|
353 |
+
';
|
354 |
+
}
|
355 |
+
|
356 |
+
return $html;
|
357 |
+
}
|
358 |
+
|
359 |
+
private function input(array $attrs = array())
|
360 |
+
{
|
361 |
+
$attrs += array(
|
362 |
+
'type' => 'text',
|
363 |
+
);
|
364 |
+
|
365 |
+
$html = '<input';
|
366 |
+
|
367 |
+
foreach ($attrs as $name => $value) {
|
368 |
+
|
369 |
+
if (!isset($value)) {
|
370 |
+
continue;
|
371 |
+
}
|
372 |
+
|
373 |
+
if (is_bool($value)) {
|
374 |
+
|
375 |
+
if ($value) {
|
376 |
+
$html .= ' '.esc_html($name);
|
377 |
+
}
|
378 |
+
|
379 |
+
continue;
|
380 |
+
}
|
381 |
+
|
382 |
+
if (is_array($value)) {
|
383 |
+
$value = join(' ', $value);
|
384 |
+
}
|
385 |
+
|
386 |
+
$html .= ' ' . esc_html($name) . '="' . esc_html($value) . '"';
|
387 |
+
}
|
388 |
+
|
389 |
+
$html .= '>';
|
390 |
+
|
391 |
+
return $html;
|
392 |
+
}
|
393 |
+
|
394 |
+
private function decimalInput(array $attrs = array())
|
395 |
+
{
|
396 |
+
if (isset($attrs['value']) && (string)$attrs['value'] !== '') {
|
397 |
+
$attrs['value'] = wc_format_localized_decimal($attrs['value']);
|
398 |
+
}
|
399 |
+
|
400 |
+
$attrs['class'] = (array)@$attrs['class'];
|
401 |
+
$attrs['class'][] = 'wc_input_decimal input-text';
|
402 |
+
|
403 |
+
return $this->input($attrs);
|
404 |
+
}
|
405 |
+
|
406 |
+
private function formRow($innerHtml, $fieldId, $classes, $data)
|
407 |
+
{
|
408 |
+
if (is_array($classes)) {
|
409 |
+
$classes = join(' ', $classes);
|
410 |
+
}
|
411 |
+
|
412 |
+
$ksesTitle = wp_kses_post(@$data['title']);
|
413 |
+
|
414 |
+
$data += array(
|
415 |
+
'desc_tip' => false,
|
416 |
+
'description' => '',
|
417 |
+
);
|
418 |
+
|
419 |
+
ob_start();
|
420 |
+
?>
|
421 |
+
<tr valign="top" class="<?php echo esc_html($classes) ?>">
|
422 |
+
<th scope="row" class="titledesc">
|
423 |
+
<?php if ($ksesTitle): ?>
|
424 |
+
<label for="<?php echo esc_attr($fieldId) ?>"><?php echo $ksesTitle ?></label>
|
425 |
+
<?php endif; ?>
|
426 |
+
<?php echo $this->settings->get_tooltip_html($data); ?>
|
427 |
+
</th>
|
428 |
+
<td class="forminp">
|
429 |
+
<fieldset>
|
430 |
+
<?php if ($ksesTitle): ?>
|
431 |
+
<legend class="screen-reader-text">
|
432 |
+
<span><?php echo $ksesTitle; ?></span>
|
433 |
+
</legend>
|
434 |
+
<?php endif; ?>
|
435 |
+
<?php echo $innerHtml ?>
|
436 |
+
<?php echo $this->settings->get_description_html($data); ?>
|
437 |
+
</fieldset>
|
438 |
+
</td>
|
439 |
+
</tr>
|
440 |
+
<?php
|
441 |
+
return ob_get_clean();
|
442 |
+
}
|
443 |
+
|
444 |
+
private function receiveString($value)
|
445 |
+
{
|
446 |
+
if (isset($value)) {
|
447 |
+
|
448 |
+
$value = stripslashes(trim($value));
|
449 |
+
|
450 |
+
if ((string)$value === '') {
|
451 |
+
$value = null;
|
452 |
+
}
|
453 |
+
}
|
454 |
+
|
455 |
+
return $value;
|
456 |
+
}
|
457 |
+
|
458 |
+
private function receiveDecimal($value, $defaultValue = null)
|
459 |
+
{
|
460 |
+
$value = $this->receiveString($value);
|
461 |
+
|
462 |
+
$value = isset($value) ? wc_format_decimal($value) : $defaultValue;
|
463 |
+
|
464 |
+
if (isset($value) && !is_numeric($value)) {
|
465 |
+
$this->settings->errors[] = "'{$value}' is not a valid decimal value";
|
466 |
+
$value = null;
|
467 |
+
}
|
468 |
+
|
469 |
+
return $value;
|
470 |
+
}
|
471 |
+
|
472 |
+
|
473 |
+
private function receiveWeightRate($input)
|
474 |
+
{
|
475 |
+
$input = (array)$input;
|
476 |
+
|
477 |
+
return array(
|
478 |
+
'cost' => $this->receiveDecimal(@$input['cost']),
|
479 |
+
'step' => $this->receiveDecimal(@$input['step']),
|
480 |
+
'skip' => $this->receiveDecimal(@$input['skip']),
|
481 |
+
);
|
482 |
+
}
|
483 |
+
}
|
WbsWcTools.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WbsWcTools
|
4 |
+
{
|
5 |
+
public static function purgeWoocommerceShippingCache()
|
6 |
+
{
|
7 |
+
global $wpdb;
|
8 |
+
|
9 |
+
$transients = $wpdb->get_col("
|
10 |
+
SELECT SUBSTR(option_name, LENGTH('_transient_') + 1)
|
11 |
+
FROM `{$wpdb->options}`
|
12 |
+
WHERE option_name LIKE '_transient_wc_ship_%'
|
13 |
+
");
|
14 |
+
|
15 |
+
foreach ($transients as $transient) {
|
16 |
+
delete_transient($transient);
|
17 |
+
}
|
18 |
+
}
|
19 |
+
}
|
assets/admin.js
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function($) {
|
2 |
+
'use strict';
|
3 |
+
|
4 |
+
var $table = $("#woowbs_shipping_methods");
|
5 |
+
|
6 |
+
$table.find('td').click(function(e) {
|
7 |
+
if (e.target == this) {
|
8 |
+
location.href = $(this).parent().data('settingsUrl')
|
9 |
+
}
|
10 |
+
});
|
11 |
+
|
12 |
+
var orderUpdatingRequest = null;
|
13 |
+
|
14 |
+
$table.find('tbody').on("sortupdate", function(event, ui) {
|
15 |
+
|
16 |
+
var ids = $(this).find('[data-profile-id]').map(function() {
|
17 |
+
return $(this).attr('data-profile-id');
|
18 |
+
}).get();
|
19 |
+
|
20 |
+
if (orderUpdatingRequest) {
|
21 |
+
orderUpdatingRequest.abort();
|
22 |
+
}
|
23 |
+
|
24 |
+
$table.addClass('in-progress');
|
25 |
+
|
26 |
+
//noinspection JSUnresolvedVariable
|
27 |
+
orderUpdatingRequest =
|
28 |
+
jQuery.post(woowbs_ajax_vars.ajax_url, {
|
29 |
+
'action': 'woowbs_update_rules_order',
|
30 |
+
'profiles': ids
|
31 |
+
})
|
32 |
+
.always(function() {
|
33 |
+
$table.removeClass('in-progress');
|
34 |
+
orderUpdatingRequest = null;
|
35 |
+
});
|
36 |
+
});
|
37 |
+
});
|
bootstrap.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Plugin Name: WooCommerce Weight Based Shipping
|
4 |
+
* Plugin URI: http://wordpress.org/plugins/weight-based-shipping-for-woocommerce/
|
5 |
+
* Description: Simple yet flexible shipping method for WooCommerce.
|
6 |
+
* Version: 4.2.3
|
7 |
+
* Author: dangoodman
|
8 |
+
* Author URI: http://tablerateshipping.com
|
9 |
+
*/
|
10 |
+
|
11 |
+
require_once(dirname(__FILE__).'/WBS_Loader.php');
|
12 |
+
WBS_Loader::loadWbs(__FILE__);
|
functions.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if (!function_exists('WC'))
|
3 |
+
{
|
4 |
+
/**
|
5 |
+
* @return Woocommerce
|
6 |
+
*/
|
7 |
+
function WC()
|
8 |
+
{
|
9 |
+
return $GLOBALS['woocommerce'];
|
10 |
+
}
|
11 |
+
}
|
12 |
+
|
13 |
+
function wbst($template, $args)
|
14 |
+
{
|
15 |
+
$result = null;
|
16 |
+
|
17 |
+
if (!empty($template))
|
18 |
+
{
|
19 |
+
if (is_array($args))
|
20 |
+
{
|
21 |
+
$replacements = array();
|
22 |
+
foreach ($args as $key => $value)
|
23 |
+
{
|
24 |
+
$replacements["{{{$key}}}"] = $value;
|
25 |
+
}
|
26 |
+
|
27 |
+
$result = strtr($template, $replacements);
|
28 |
+
}
|
29 |
+
else
|
30 |
+
{
|
31 |
+
$result = preg_replace('/\{\{.*?\}\}/', $args, $template);
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
return $result;
|
36 |
+
}
|
37 |
+
?>
|
legacy.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class WBS_Shipping_Rate_Override
|
3 |
+
{
|
4 |
+
private $class;
|
5 |
+
private $fee;
|
6 |
+
private $rate;
|
7 |
+
private $weightStep;
|
8 |
+
|
9 |
+
public function getWeightStep()
|
10 |
+
{
|
11 |
+
return $this->weightStep;
|
12 |
+
}
|
13 |
+
|
14 |
+
public function getClass()
|
15 |
+
{
|
16 |
+
return $this->class;
|
17 |
+
}
|
18 |
+
|
19 |
+
public function getRate()
|
20 |
+
{
|
21 |
+
return $this->rate;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getFee()
|
25 |
+
{
|
26 |
+
return $this->fee;
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
class WBS_Shipping_Class_Override_Set
|
31 |
+
{
|
32 |
+
private $overrides;
|
33 |
+
|
34 |
+
public function getOverrides()
|
35 |
+
{
|
36 |
+
return $this->overrides;
|
37 |
+
}
|
38 |
+
}
|
readme.txt
ADDED
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== WooCommerce Weight Based Shipping ===
|
2 |
+
Contributors: dangoodman
|
3 |
+
Tags: ecommerce, woocommerce, shipping, woocommerce shipping, weight-based shipping, conditional free shipping,
|
4 |
+
conditional flat rate, table rate shipping, weight, subtotal, country, shipping classes
|
5 |
+
Requires at least: 3.8
|
6 |
+
Tested up to: 4.7
|
7 |
+
WC requires at least: 2.1
|
8 |
+
WC tested up to: 2.7
|
9 |
+
Stable tag: trunk
|
10 |
+
|
11 |
+
|
12 |
+
Simple yet flexible weight-based shipping for WooCommerce
|
13 |
+
|
14 |
+
== Description ==
|
15 |
+
|
16 |
+
Weight Based Shipping is a simple yet flexible shipping method for WooCommerce focused mainly on order weight (but not limited to) to calculate shipping cost. Plugin allows you to add multiple rules based on various conditions.
|
17 |
+
|
18 |
+
<br>
|
19 |
+
|
20 |
+
= Features =
|
21 |
+
|
22 |
+
<p></p>
|
23 |
+
<ul>
|
24 |
+
<li>
|
25 |
+
<b>Order weight, subtotal and destination</b><br>
|
26 |
+
Create as many shipping rules as you need for different order destinations, weight and subtotal ranges.<br><br>
|
27 |
+
</li>
|
28 |
+
<li>
|
29 |
+
<b>Flexible Price Calculation</b><br>
|
30 |
+
Each rule can be configured to expose a constant price (like Flat Rate) or a progressive price based on cart weight, or both.<br><br>
|
31 |
+
</li>
|
32 |
+
<li>
|
33 |
+
<b>Conditional Free Shipping</b><br>
|
34 |
+
In some cases you want to ship for free depending on subtotal, total weight or some other condition. That can be achieved in a moment with the plugin.<br><br>
|
35 |
+
</li>
|
36 |
+
<li>
|
37 |
+
<b>Shipping Classes Support</b><br>
|
38 |
+
For each shipping class you have you can override the way shipping price is calculated for it.<br><br>
|
39 |
+
</li>
|
40 |
+
</ul>
|
41 |
+
|
42 |
+
See <a href="https://wordpress.org/plugins/weight-based-shipping-for-woocommerce/screenshots/">screenshots</a> for the list of all supported options.
|
43 |
+
<br><br>
|
44 |
+
|
45 |
+
<blockquote>
|
46 |
+
Also, check out our <a href="http://tablerateshipping.com">advanced table rate shipping plugin for WooCommerce</a>.<br>
|
47 |
+
<br>
|
48 |
+
</blockquote>
|
49 |
+
|
50 |
+
== Changelog ==
|
51 |
+
|
52 |
+
= 4.2.3 =
|
53 |
+
* Fix links to premium plugins
|
54 |
+
|
55 |
+
= 4.2.2 =
|
56 |
+
* Fix rules not imported from an older version when updating from pre-4.0 to 4.2.0 or 4.2.1
|
57 |
+
|
58 |
+
= 4.2.1 =
|
59 |
+
* Fix saving rules order
|
60 |
+
|
61 |
+
= 4.2.0 =
|
62 |
+
* Allow sorting rules by drag'n'drop in admin panel
|
63 |
+
|
64 |
+
= 4.1.4 =
|
65 |
+
* WooCommerce 2.6 compatibility fixes
|
66 |
+
|
67 |
+
= 4.1.3 =
|
68 |
+
* Minimize chances of a float-point rounding error in the weight step count calculation (https://wordpress.org/support/topic/weight-rate-charge-skip-calculate)
|
69 |
+
|
70 |
+
= 4.1.2 =
|
71 |
+
* Don't fail on invalid settings, allow editing them instead
|
72 |
+
|
73 |
+
= 4.1.1 =
|
74 |
+
* Backup old settings on upgrade from pre-4.0 versions
|
75 |
+
|
76 |
+
= 4.1.0 =
|
77 |
+
* Fix WC_Settings_API->get_field_key() missing method usage on WC 2.3.x
|
78 |
+
* Use package passed to calculate_shipping() funciton instead of global cart object for better integration with 3d-party plugins
|
79 |
+
* Get rid of wbs_remap_shipping_class hook
|
80 |
+
* Use class autoloader for better performance and code readability
|
81 |
+
|
82 |
+
= 4.0.0 =
|
83 |
+
* Admin UI redesign
|
84 |
+
|
85 |
+
= 3.0.0 =
|
86 |
+
* Country states/regions targeting support
|
87 |
+
|
88 |
+
= 2.6.9 =
|
89 |
+
* Fixed: inconsistent decimal input handling in Shipping Classes section (https://wordpress.org/support/topic/please-enter-in-monetary-decimal-issue)
|
90 |
+
|
91 |
+
= 2.6.8 =
|
92 |
+
* Fixed: plugin settings are not changed on save with WooCommerce 2.3.10 (WooCommerce 2.3.10 compatibility issue)
|
93 |
+
|
94 |
+
= 2.6.6 =
|
95 |
+
* Introduced 'wbs_profile_settings_form' filter for better 3d-party extensions support
|
96 |
+
* Removed partial localization
|
97 |
+
|
98 |
+
= 2.6.5 =
|
99 |
+
* Min/Max Shipping Price options
|
100 |
+
|
101 |
+
= 2.6.3 =
|
102 |
+
* Improved upgrade warning system
|
103 |
+
* Fixed warning about Shipping Classes Overrides changes
|
104 |
+
|
105 |
+
= 2.6.2 =
|
106 |
+
* Fixed Shipping Classes Overrides: always apply base Handling Fee
|
107 |
+
|
108 |
+
= 2.6.1 =
|
109 |
+
* Introduced "Subtotal With Tax" option
|
110 |
+
|
111 |
+
= 2.6.0 =
|
112 |
+
* Min/Max Subtotal condition support
|
113 |
+
|
114 |
+
= 2.5.1 =
|
115 |
+
* Introduce "wbs_remap_shipping_class" filter to provide 3dparty plugins an ability to alter shipping cost calculation
|
116 |
+
* Wordpress 4.1 compatibility testing
|
117 |
+
|
118 |
+
= 2.5.0 =
|
119 |
+
|
120 |
+
* Shipping classes support
|
121 |
+
* Ability to choose all countries except specified
|
122 |
+
* Select All/None buttons for countries
|
123 |
+
* Purge shipping price calculations cache on configuration changes to reflect actual config immediatelly
|
124 |
+
* Profiles table look tweaks
|
125 |
+
* Other small tweaks
|
126 |
+
|
127 |
+
= 2.4.2 =
|
128 |
+
|
129 |
+
* Fixed: deleting non-currently selected configuration deletes first configuration from the list
|
130 |
+
|
131 |
+
= 2.4.1 =
|
132 |
+
|
133 |
+
* Updated pot-file required for translations
|
134 |
+
* Added three nice buttons to plugin settings page
|
135 |
+
* Prevent buttons in Actions column from wrapping on multiple lines
|
136 |
+
|
137 |
+
= 2.4.0 =
|
138 |
+
|
139 |
+
* By default, apply Shipping Rate to the extra weight part exceeding Min Weight. Also a checkbox added to switch off this feature.
|
140 |
+
|
141 |
+
= 2.3.0 =
|
142 |
+
|
143 |
+
* Duplicate profile feature
|
144 |
+
* New 'Weight Step' option for rough gradual shipping price calculation
|
145 |
+
* Added more detailed description to the Handling Fee and Shipping Rate fields to make their purpose clear
|
146 |
+
* Plugin prepared for localization
|
147 |
+
* Refactoring
|
148 |
+
|
149 |
+
= 2.2.3 =
|
150 |
+
|
151 |
+
* Fixed: first time saving settings with fresh install does not save anything while reporting successful saving.
|
152 |
+
* Replace short php tags with their full equivalents to make code more portable.
|
153 |
+
|
154 |
+
= 2.2.2 =
|
155 |
+
|
156 |
+
Fix "parse error: syntax error, unexpected T_FUNCTION in woocommerce-weight-based-shipping.php on line 610" http://wordpress.org/support/topic/fatal-error-1164.
|
157 |
+
|
158 |
+
= 2.2.1 =
|
159 |
+
|
160 |
+
Allow zero weight shipping. Thus only Handling Fee is added to the final price.
|
161 |
+
|
162 |
+
Previously, weight based shipping option has not been shown to user if total weight of their cart is zero. Since version 2.2.1 this is changed so shipping option is available to user with price set to Handling Fee. If it does not suite your needs well you can return previous behavior by setting Min Weight to something a bit greater zero, e.g. 0.001, so that zero-weight orders will not match constraints and the shipping option will not be shown.
|
163 |
+
|
164 |
+
== Upgrade Notice ==
|
165 |
+
|
166 |
+
= 2.2.1 =
|
167 |
+
|
168 |
+
Allow zero weight shipping. Thus only Handling Fee is added to the final price.
|
169 |
+
|
170 |
+
Previously, weight based shipping option has not been shown to user if total weight of their cart is zero. Since version 2.2.1 this is changed so shipping option is available to user with price set to Handling Fee. If it does not suite your needs well you can return previous behavior by setting Min Weight to something a bit greater zero, e.g. 0.001, so that zero-weight orders will not match constraints and the shipping option will not be shown.
|
171 |
+
|
172 |
+
|
173 |
+
== Screenshots ==
|
174 |
+
|
175 |
+
1. A configuration example
|
176 |
+
2. Another rule settings
|
177 |
+
3. How that could look to customer
|