• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlocati / ip-lib / 17978929001

24 Sep 2025 01:53PM UTC coverage: 98.988% (+0.2%) from 98.751%
17978929001

push

github

web-flow
Update php-cs-fixer, simplify tests, remove Scrutinizer (#107)

11 of 11 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

1174 of 1186 relevant lines covered (98.99%)

205.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.77
/src/Range/AbstractRange.php
1
<?php
2

3
namespace IPLib\Range;
4

5
use IPLib\Address\AddressInterface;
6
use IPLib\Address\IPv4;
7
use IPLib\Address\IPv6;
8
use IPLib\Address\Type as AddressType;
9
use IPLib\Factory;
10
use IPLib\Service\BinaryMath;
11
use OutOfBoundsException;
12

13
/**
14
 * Base class for range classes.
15
 */
16
abstract class AbstractRange implements RangeInterface
17
{
18
    /**
19
     * {@inheritdoc}
20
     *
21
     * @see \IPLib\Range\RangeInterface::getRangeType()
22
     */
23
    public function getRangeType()
24
    {
25
        if ($this->rangeType === null) {
242✔
26
            $addressType = $this->getAddressType();
242✔
27
            if ($addressType === AddressType::T_IPv6 && Subnet::get6to4()->containsRange($this)) {
242✔
28
                $this->rangeType = Factory::getRangeFromBoundaries($this->fromAddress->toIPv4(), $this->toAddress->toIPv4())->getRangeType();
9✔
29
            } else {
30
                switch ($addressType) {
31
                    case AddressType::T_IPv4:
32
                        $defaultType = IPv4::getDefaultReservedRangeType();
170✔
33
                        $reservedRanges = IPv4::getReservedRanges();
170✔
34
                        break;
170✔
35
                    case AddressType::T_IPv6:
36
                        $defaultType = IPv6::getDefaultReservedRangeType();
63✔
37
                        $reservedRanges = IPv6::getReservedRanges();
63✔
38
                        break;
63✔
39
                    default:
40
                        throw new \Exception('@todo'); // @codeCoverageIgnore
41
                }
42
                $rangeType = null;
233✔
43
                foreach ($reservedRanges as $reservedRange) {
233✔
44
                    $rangeType = $reservedRange->getRangeType($this);
233✔
45
                    if ($rangeType !== null) {
233✔
46
                        break;
198✔
47
                    }
48
                }
49
                $this->rangeType = $rangeType === null ? $defaultType : $rangeType;
233✔
50
            }
51
        }
52

53
        return $this->rangeType === false ? null : $this->rangeType;
242✔
54
    }
55

56
    /**
57
     * {@inheritdoc}
58
     *
59
     * @see \IPLib\Range\RangeInterface::getAddressAtOffset()
60
     */
61
    public function getAddressAtOffset($n)
62
    {
63
        if (is_int($n)) {
22✔
64
            $positive = $n >= 0;
13✔
65
            if ($positive === false) {
13✔
66
                $nPlus1 = $n + 1;
5✔
67
            }
68
        } elseif (($s = BinaryMath::getInstance()->normalizeIntegerString($n)) !== '') {
9✔
69
            $n = $s;
8✔
70
            $positive = $n[0] !== '-';
8✔
71
            if ($positive === false) {
8✔
UNCOV
72
                $nPlus1 = BinaryMath::getInstance()->add1ToIntegerString($n);
×
73
            }
74
        } else {
75
            return null;
1✔
76
        }
77
        if ($positive) {
21✔
78
            $start = Factory::parseAddressString($this->getComparableStartString());
16✔
79
            $address = $start->getAddressAtOffset($n);
16✔
80
        } else {
81
            $end = Factory::parseAddressString($this->getComparableEndString());
5✔
82
            $address = $end->getAddressAtOffset($nPlus1);
5✔
83
        }
84

85
        if ($address === null) {
21✔
86
            return null;
2✔
87
        }
88

89
        return $this->contains($address) ? $address : null;
19✔
90
    }
91

92
    /**
93
     * {@inheritdoc}
94
     *
95
     * @see \IPLib\Range\RangeInterface::contains()
96
     */
97
    public function contains(AddressInterface $address)
98
    {
99
        $result = false;
278✔
100
        if ($address->getAddressType() === $this->getAddressType()) {
278✔
101
            $cmp = $address->getComparableString();
278✔
102
            $from = $this->getComparableStartString();
278✔
103
            if ($cmp >= $from) {
278✔
104
                $to = $this->getComparableEndString();
273✔
105
                if ($cmp <= $to) {
273✔
106
                    $result = true;
227✔
107
                }
108
            }
109
        }
110

111
        return $result;
278✔
112
    }
113

114
    /**
115
     * {@inheritdoc}
116
     *
117
     * @see \IPLib\Range\RangeInterface::containsRange()
118
     */
119
    public function containsRange(RangeInterface $range)
120
    {
121
        $result = false;
89✔
122
        if ($range->getAddressType() === $this->getAddressType()) {
89✔
123
            $myStart = $this->getComparableStartString();
89✔
124
            $itsStart = $range->getComparableStartString();
89✔
125
            if ($itsStart >= $myStart) {
89✔
126
                $myEnd = $this->getComparableEndString();
51✔
127
                $itsEnd = $range->getComparableEndString();
51✔
128
                if ($itsEnd <= $myEnd) {
51✔
129
                    $result = true;
21✔
130
                }
131
            }
132
        }
133

134
        return $result;
89✔
135
    }
136

137
    /**
138
     * {@inheritdoc}
139
     *
140
     * @see \IPLib\Range\RangeInterface::split()
141
     */
142
    public function split($networkPrefix, $forceSubnet = false)
143
    {
144
        $networkPrefix = (int) $networkPrefix;
65✔
145
        $myNetworkPrefix = $this->getNetworkPrefix();
65✔
146
        if ($networkPrefix === $myNetworkPrefix) {
65✔
147
            return array(
18✔
148
                $forceSubnet ? $this->asSubnet() : $this,
18✔
149
            );
18✔
150
        }
151
        if ($networkPrefix < $myNetworkPrefix) {
47✔
152
            throw new OutOfBoundsException("The value of the \$networkPrefix parameter can't be smaller than the network prefix of the range ({$myNetworkPrefix})");
16✔
153
        }
154
        $startIp = $this->getStartAddress();
31✔
155
        $maxPrefix = $startIp::getNumberOfBits();
31✔
156
        if ($networkPrefix > $maxPrefix) {
31✔
157
            throw new OutOfBoundsException("The value of the \$networkPrefix parameter can't be larger than the maximum network prefix of the range ({$maxPrefix})");
13✔
158
        }
159
        if ($startIp instanceof IPv4) {
18✔
160
            $one = IPv4::fromBytes(array(0, 0, 0, 1));
14✔
161
        } elseif ($startIp instanceof IPv6) {
4✔
162
            $one = IPv6::fromBytes(array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1));
4✔
163
        }
164
        $delta = $one->shift($networkPrefix - $maxPrefix);
18✔
165
        $result = array();
18✔
166
        while (true) {
18✔
167
            $range = Subnet::parseString("{$startIp}/{$networkPrefix}");
18✔
168
            if (!$forceSubnet && $this instanceof Pattern) {
18✔
169
                $range = $range->asPattern() ?: $range;
6✔
170
            }
171
            $result[] = $range;
18✔
172
            $startIp = $startIp->add($delta);
18✔
173
            if ($startIp === null || !$this->contains($startIp)) {
18✔
174
                break;
18✔
175
            }
176
        }
177

178
        return $result;
18✔
179
    }
180
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc