Passed
Push — 3.x ( 33350c...688d36 )
by Doug
14:36
created

InfalliblePacker::sanityPrecheck()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 21
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 15
c 0
b 0
f 0
nc 7
nop 0
dl 0
loc 21
ccs 0
cts 4
cp 0
crap 56
rs 8.8333
1
<?php
2
/**
3
 * Box packing (3D bin packing, knapsack problem).
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace DVDoug\BoxPacker;
10
11
use function count;
12
13
/**
14
 * A version of the packer that swallows internal exceptions.
15
 *
16
 * @author Doug Wright
17
 */
18
class InfalliblePacker extends Packer
19
{
20
    /**
21
     * @var ItemList
22
     */
23
    protected $unpackedItems;
24
25
    /**
26
     * InfalliblePacker constructor.
27
     */
28
    public function __construct()
29
    {
30
        $this->unpackedItems = new ItemList();
31
        parent::__construct();
32
    }
33
34
    /**
35
     * Return the items that couldn't be packed.
36
     */
37
    public function getUnpackedItems(): ItemList
38
    {
39
        return $this->unpackedItems;
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function pack(): PackedBoxList
46
    {
47
        $this->sanityPrecheck();
48
        while (true) {
49
            try {
50
                return parent::pack();
51
            } catch (NoBoxesAvailableException $e) {
52
                $this->unpackedItems->insert($e->getItem());
53
                $this->items->remove($e->getItem());
54
            }
55
        }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return DVDoug\BoxPacker\PackedBoxList. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
56
    }
57
58
    private function sanityPrecheck(): void
59
    {
60
        $cache = [];
61
62
        foreach ($this->items as $item) {
63
            $cacheKey = $item->getWidth() .
64
                '|' .
65
                $item->getLength() .
66
                '|' .
67
                $item->getDepth() .
68
                '|' .
69
                ($item->getKeepFlat() ? '2D' : '3D');
70
71
            foreach ($this->boxes as $box) {
72
                if ($item->getWeight() <= ($box->getMaxWeight() - $box->getEmptyWeight()) && (isset($cache[$cacheKey]) || (count((new OrientatedItemFactory($box))->getPossibleOrientations($item, null, $box->getInnerWidth(), $box->getInnerLength(), $box->getInnerDepth(), 0, 0, 0, new PackedItemList())) > 0))) {
73
                    $cache[$cacheKey] = true;
74
                    continue 2;
75
                }
76
            }
77
            $this->unpackedItems->insert($item);
78
            $this->items->remove($item);
79
        }
80
    }
81
}
82