Passed
Push — master ( b79dbd...29a054 )
by Doug
08:25 queued 05:38
created

InfalliblePacker::sanityPrecheck()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 21
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 15
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 21
ccs 16
cts 16
cp 1
crap 6
rs 9.2222
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
use DVDoug\BoxPacker\Exception\NoBoxesAvailableException;
13
14
/**
15
 * A version of the packer that swallows internal exceptions.
16
 *
17
 * @author Doug Wright
18
 */
19
class InfalliblePacker extends Packer
20
{
21
    /**
22
     * @var ItemList
23
     */
24
    protected $unpackedItems;
25
26
    /**
27
     * InfalliblePacker constructor.
28
     */
29 6
    public function __construct()
30
    {
31 6
        $this->unpackedItems = new ItemList();
32 6
        parent::__construct();
33 6
    }
34
35
    /**
36
     * Return the items that couldn't be packed.
37
     */
38 6
    public function getUnpackedItems(): ItemList
39
    {
40 6
        return $this->unpackedItems;
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46 6
    public function pack(): PackedBoxList
47
    {
48 6
        $this->sanityPrecheck();
49 6
        while (true) {
50
            try {
51 6
                return parent::pack();
52 2
            } catch (NoBoxesAvailableException $e) {
53 2
                $this->unpackedItems->insert($e->getItem());
54 2
                $this->items->remove($e->getItem());
55
            }
56
        }
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...
57
    }
58
59 6
    private function sanityPrecheck(): void
60
    {
61 6
        $cache = [];
62
63 6
        foreach ($this->items as $item) {
64 6
            $cacheKey = $item->getWidth() .
65 6
                '|' .
66 6
                $item->getLength() .
67 6
                '|' .
68 6
                $item->getDepth() .
69 6
                '|' .
70 6
                $item->getAllowedRotations();
71
72 6
            foreach ($this->boxes as $box) {
73 6
                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))) {
74 6
                    $cache[$cacheKey] = true;
75 6
                    continue 2;
76
                }
77
            }
78 6
            $this->unpackedItems->insert($item);
79 6
            $this->items->remove($item);
80
        }
81 6
    }
82
}
83