Passed
Push — master ( 2b1200...dfc48c )
by Victor
01:25
created

TruncatableTrait   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 53
dl 0
loc 139
rs 10
c 0
b 0
f 0
wmc 22

6 Methods

Rating   Name   Duplication   Size   Complexity  
A compareToLimit() 0 11 3
A minBound() 0 5 1
B truncate() 0 32 7
B pad() 0 17 7
A outerBound() 0 11 3
A maxBound() 0 5 1
1
<?php
2
/**
3
 * User: vtoulouse
4
 * Date: 25/01/2019
5
 * Time: 16:26
6
 */
7
8
namespace Vctls\IntervalGraph;
9
10
11
trait TruncatableTrait
12
{
13
    /**
14
     * Truncate all intervals to the given lower and upper limits.
15
     *
16
     * @param array $intervals
17
     * @param mixed $lowerLimit
18
     * @param mixed $upperLimit
19
     * @param bool $padding Add null value intervals between the bounds and the first and last bounds.
20
     * @return array
21
     */
22
    public static function truncate(array $intervals, $lowerLimit = null, $upperLimit = null, $padding = false)
23
    {
24
        $limits = [
25
            0 => $lowerLimit,
26
            1 => $upperLimit
27
        ];
28
        foreach ($limits as $type => $limit) {
29
            if (isset($limit)) {
30
                foreach ($intervals as $key => $interval) {
31
                    if (self::compareToLimit($interval[$type], $limit, $type)) {
32
                        if (self::compareToLimit($interval[(int)!$type], $limit, $type)) {
33
                            // If both bounds are beyond the limit, set the interval to false for removal.
34
                            $intervals[$key] = false;
35
                        } else {
36
                            // If only the outer bound is beyond the limit, set it to the limit value.
37
                            $intervals[$key][$type] = $limit;
38
                        }
39
                    }
40
                }
41
42
                // Remove false elements.
43
                $intervals = array_filter($intervals);
44
45
                // If padding is required and a limit is set and is beyond the limit,
46
                // add a valueless interval between that bound and the limit.
47
                if ($padding) {
48
                    self::pad($intervals, $limit, $type);
49
                }
50
            }
51
        }
52
53
        return $intervals;
54
    }
55
56
    /**
57
     * Pad the interval array if needed, from left OR right depending on the type.
58
     *
59
     * @param $intervals
60
     * @param $value
61
     * @param $type
62
     */
63
    public static function pad(&$intervals, $value, $type)
64
    {
65
        switch ($type) {
66
            case 0:
67
                $bound = self::minBound($intervals);
68
                if (isset($bound) && $bound > $value) {
69
                    array_unshift($intervals, [$value, $bound]);
70
                }
71
                break;
72
            case 1:
73
                $bound = self::maxBound($intervals);
74
                if (isset($bound) && $bound < $value) {
75
                    array_push($intervals, [$bound, $value]);
76
                }
77
                break;
78
            default:
79
                throw new \InvalidArgumentException("Type should be 0 (low padding) or 1 (high padding).");
80
        }
81
    }
82
83
    /**
84
     * Return the minimum or maximum bound depending on the type.
85
     *
86
     * @param $intervals
87
     * @param int $type 0 (min) or 1 (max)
88
     * @return mixed
89
     */
90
    public static function outerBound($intervals, int $type)
91
    {
92
        switch ($type) {
93
            case 0:
94
                return self::minBound($intervals);
95
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
96
            case 1:
97
                return self::maxBound($intervals);
98
                break;
99
            default:
100
                throw new \InvalidArgumentException("Type must be 0 (min) or 1 (max)");
101
        }
102
    }
103
104
    /**
105
     * Get the minimum bound in an array of intervals.
106
     *
107
     * @param $intervals
108
     * @return mixed
109
     */
110
    public static function minBound($intervals)
111
    {
112
        $bounds = array_column($intervals, 0);
113
        sort($bounds);
114
        return array_shift($bounds);
115
    }
116
117
    /**
118
     * Get the maximum bound in an array of intervals.
119
     *
120
     * @param $intervals
121
     * @return mixed
122
     */
123
    public static function maxBound($intervals)
124
    {
125
        $bounds = array_column($intervals, 1);
126
        sort($bounds);
127
        return array_pop($bounds);
128
    }
129
130
    /**
131
     * Checks if the value is inferior to a lower (type 0) limit,
132
     * or superior to an upper (type 1) limit.
133
     *
134
     * @param $value
135
     * @param $limit
136
     * @param int $type 0 (lower limit) or 1 (upper limit)
137
     * @return bool
138
     */
139
    private static function compareToLimit($value, $limit, int $type)
140
    {
141
        switch ($type) {
142
            case 0 :
143
                return $value < $limit;
144
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
145
            case 1 :
146
                return $value > $limit;
147
                break;
148
            default :
149
                throw new \InvalidArgumentException("Limit type must be 0 (lower) or 1 (upper)");
150
        }
151
    }
152
}