Passed
Push — master ( c38e78...642601 )
by Stephen
50s queued 12s
created

ChunkSizer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 4
dl 0
loc 6
rs 10
1
<?php
2
3
namespace Sfneal\Helpers\Arrays\Utils;
4
5
use Sfneal\Actions\Action;
6
7
class ChunkSizer extends Action
8
{
9
    /**
10
     * @var int
11
     */
12
    private $array_size;
13
14
    /**
15
     * @var int
16
     */
17
    private $min;
18
19
    /**
20
     * @var int|null
21
     */
22
    private $max;
23
24
    /**
25
     * @var int
26
     */
27
    private $divisor;
28
29
    /**
30
     * ChunkSizer constructor.
31
     *
32
     * @param int $array_size size of the array
33
     * @param int $min minimum chunk size
34
     * @param int|null $max maximum chunk size
35
     * @param int $divisor
36
     */
37
    public function __construct(int $array_size, int $min = 0, int $max = null, int $divisor = 2)
38
    {
39
        $this->array_size = $array_size;
40
        $this->min = $min;
41
        $this->max = $max;
42
        $this->divisor = $divisor;
43
    }
44
45
    /**
46
     * Return a best fit chunk size to be passed to array_chunks functions.
47
     *
48
     * Calculates the remainder of array sizes divided by the divisor
49
     * using modulus division.  Continues to calculate remainders until
50
     * the remainder is zero, signifying evenly sized chunks, or the
51
     * divisor is equal to the array size.  If a remainder of zero is not
52
     * found the lowest remainder is returned.
53
     *
54
     * @return int $remainder lowest calculated remainder
55
     */
56
    public function execute(): int
57
    {
58
        // If the size of the array is a perfect square, return the square root
59
        if (gmp_perfect_square($this->array_size) == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
60
            return sqrt($this->array_size);
61
        }
62
63
        // If min and max are the same return that value
64
        elseif ($this->min == $this->max) {
65
            return $this->min;
66
        }
67
68
        $this->max = (isset($this->max) ? $this->max : $this->array_size);
69
        $sizes = [];
70
        while ($this->divisor < $this->max) {
71
            $sizes[$this->divisor] = [
72
                // Number of chunks
73
                'rows'=> floor($this->array_size / $this->divisor),
74
75
                // Items in each chunk
76
                'cols' => $this->divisor,
77
78
                // Left over items in last chunk
79
                'remainder' => $this->array_size % $this->divisor,
80
            ];
81
            $this->divisor++;
82
        }
83
84
        // Filter sizes by column values
85
        return min(array_filter(
86
            array_column($sizes, 'cols', 'cols'),
87
            function ($size) use ($sizes) {
88
                return
89
                    // Check that the remainder is no more than half of the number of columns
90
                    ($sizes[$size]['remainder'] == 0 || $sizes[$size]['remainder'] >= $size / 2) &&
91
92
                    // Check that the number of columns is greater than or equal than min and less than or equal than max
93
                    $this->min <= $size && $size <= $this->max;
94
            }
95
        ));
96
    }
97
}
98