Created
December 19, 2016 18:29
-
-
Save vensires/f06ca627800b9c6808e9b47b31bec772 to your computer and use it in GitHub Desktop.
Divides an array of different products weights to packages containing at most $package_max_weight weight and $package_max_items items. You could use this function to calculate shipping based on package weight instead of product weight.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Divides product weights into packages. | |
* | |
* @param array $weights | |
* An array of product weights. | |
* @param int $package_max_weight | |
* The maximum weight of a package. Set to 0 to not allow limit per weight. | |
* @param int $package_max_items | |
* The maximum number of items per package. Set to 0 to not allow limit per items. | |
* | |
* @return array | |
* An array of package weights. | |
*/ | |
function commerce_shipping_packages_product_weights_to_packages($weights, $package_max_weight = 0, $package_max_items = 0) { | |
// Sort weights from maximum to minimum. | |
rsort($weights); | |
// An array to hold the packages. | |
$packages = array(); | |
// An array to hold the parsed weights. | |
$parsed = array(); | |
// A variable to hold the package's weight. | |
$package_weight = 0; | |
// A variable to hold the package's total items. | |
$package_items = 0; | |
// Get the latest (equivalent) key. | |
end($weights); | |
$eqweight_index = key($weights); | |
// Latest PHP versions don't need this since foreach automatically resets. | |
reset($weights); | |
foreach ($weights as $index => $weight) { | |
if (in_array($index, $parsed)) { | |
// Reached an already parsed value. Assume all values were parsed. | |
if ($package_weight > 0 && $package_items > 0) { | |
// There are still items without a package. | |
$packages[] = $package_weight; | |
} | |
break; | |
} | |
if ($package_max_items) { | |
// Check number of items in package including this item. | |
if ($package_items + 1 > $package_max_items) { | |
$packages[] = $package_weight; | |
$package_weight = 0; | |
$package_items = 0; | |
} | |
} | |
// Check package weight including this weight. | |
if ($package_max_weight) { | |
if ($weight > $package_max_weight) { | |
// This item is already heavy enough. Create a new package for any | |
// previous items. Create a new package for this item too. | |
$parsed[] = $index; | |
if ($package_weight) { | |
$packages[] = $package_weight; | |
} | |
$packages[] = $weight; | |
$package_items = 0; | |
$package_weight = 0; | |
continue; | |
} | |
elseif ($package_weight + $weight > $package_max_weight) { | |
// This package already contains heavy enough items. Create a new | |
// package for them. Then add this weight as a package base weight. | |
$packages[] = $package_weight; | |
$parsed[] = $index; | |
$package_items = 1; | |
$package_weight = $weight; | |
} | |
else { | |
// This item can be stored in the current package. | |
$package_weight += $weight; | |
$package_items++; | |
$parsed[] = $index; | |
} | |
if (isset($weights[$eqweight_index]) && !in_array($eqweight_index, $parsed)) { | |
// There is a non-parsed equivalent weight. | |
if (!$package_max_items || $package_max_items && $package_max_items > $package_items) { | |
// No package max items configured or didn't yet reach max items. | |
if ($package_weight + $weights[$eqweight_index] <= $package_max_weight) { | |
// Haven't yet reached maximum weight. | |
$package_weight += $weights[$eqweight_index]; | |
$package_items++; | |
$parsed[] = $eqweight_index; | |
// Decrease the equivalent weight index key by 1. | |
$eqweight_index--; | |
} | |
} | |
} | |
} | |
} | |
return $packages; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment