1<?php
2
3namespace IPLib\Address;
4
5use IPLib\Range\RangeInterface;
6
7/**
8 * Represents an IP address range with an assigned range type.
9 */
10class AssignedRange
11{
12    /**
13     * The range definition.
14     *
15     * @var \IPLib\Range\RangeInterface
16     */
17    protected $range;
18
19    /**
20     * The range type.
21     *
22     * @var int one of the \IPLib\Range\Type::T_ constants
23     */
24    protected $type;
25
26    /**
27     * The list of exceptions for this range type.
28     *
29     * @var \IPLib\Address\AssignedRange[]
30     */
31    protected $exceptions;
32
33    /**
34     * Initialize the instance.
35     *
36     * @param \IPLib\Range\RangeInterface $range the range definition
37     * @param int $type The range type (one of the \IPLib\Range\Type::T_ constants)
38     * @param \IPLib\Address\AssignedRange[] $exceptions the list of exceptions for this range type
39     */
40    public function __construct(RangeInterface $range, $type, array $exceptions = array())
41    {
42        $this->range = $range;
43        $this->type = $type;
44        $this->exceptions = $exceptions;
45    }
46
47    /**
48     * Get the range definition.
49     *
50     * @return \IPLib\Range\RangeInterface
51     */
52    public function getRange()
53    {
54        return $this->range;
55    }
56
57    /**
58     * Get the range type.
59     *
60     * @return int one of the \IPLib\Range\Type::T_ constants
61     */
62    public function getType()
63    {
64        return $this->type;
65    }
66
67    /**
68     * Get the list of exceptions for this range type.
69     *
70     * @return \IPLib\Address\AssignedRange[]
71     */
72    public function getExceptions()
73    {
74        return $this->exceptions;
75    }
76
77    /**
78     * Get the assigned type for a specific address.
79     *
80     * @param \IPLib\Address\AddressInterface $address
81     *
82     * @return int|null return NULL of the address is outside this address; a \IPLib\Range\Type::T_ constant otherwise
83     */
84    public function getAddressType(AddressInterface $address)
85    {
86        $result = null;
87        if ($this->range->contains($address)) {
88            foreach ($this->exceptions as $exception) {
89                $result = $exception->getAddressType($address);
90                if ($result !== null) {
91                    break;
92                }
93            }
94            if ($result === null) {
95                $result = $this->type;
96            }
97        }
98
99        return $result;
100    }
101
102    /**
103     * Get the assigned type for a specific address range.
104     *
105     * @param \IPLib\Range\RangeInterface $range
106     *
107     * @return int|null|false return NULL of the range is fully outside this range; false if it's partly crosses this range (or it contains mixed types); a \IPLib\Range\Type::T_ constant otherwise
108     */
109    public function getRangeType(RangeInterface $range)
110    {
111        $myStart = $this->range->getComparableStartString();
112        $rangeEnd = $range->getComparableEndString();
113        if ($myStart > $rangeEnd) {
114            $result = null;
115        } else {
116            $myEnd = $this->range->getComparableEndString();
117            $rangeStart = $range->getComparableStartString();
118            if ($myEnd < $rangeStart) {
119                $result = null;
120            } elseif ($rangeStart < $myStart || $rangeEnd > $myEnd) {
121                $result = false;
122            } else {
123                $result = null;
124                foreach ($this->exceptions as $exception) {
125                    $result = $exception->getRangeType($range);
126                    if ($result !== null) {
127                        break;
128                    }
129                }
130                if ($result === null) {
131                    $result = $this->getType();
132                }
133            }
134        }
135
136        return $result;
137    }
138}
139