finalize classes
[m6w6/seekat] / lib / API / Links.php
1 <?php
2
3 namespace seekat\API;
4
5 use seekat\Exception\UnexpectedValueException;
6 use http\ {
7 Header,
8 Params,
9 QueryString,
10 Url
11 };
12 use Serializable;
13
14 final class Links implements Serializable
15 {
16 /**
17 * Parsed "Link" relations
18 * @var Params
19 */
20 private $params;
21
22 /**
23 * Parsed "Link" relations
24 * @var array
25 */
26 private $relations = [];
27
28 /**
29 * Parse the hypermedia link header
30 *
31 * @param Header $links The Link header
32 * @throws UnexpectedValueException
33 */
34 function __construct(Header $links) {
35 if (strcasecmp($links->name, "Link")) {
36 throw new UnexpectedValueException("Expected 'Link' header, got: '{$links->name}'");
37 }
38 $this->unserialize($links->value);
39 }
40
41 /**
42 * @return string
43 */
44 function __toString() : string {
45 return $this->serialize();
46 }
47
48 /**
49 * @return string
50 */
51 function serialize() {
52 return (string) $this->params;
53 }
54
55 /**
56 * @param string $links
57 */
58 function unserialize($links) {
59 $this->params = new Params($links, ",", ";", "=",
60 Params::PARSE_RFC5988 | Params::PARSE_ESCAPED);
61 if ($this->params->params) {
62 foreach ($this->params->params as $link => $param) {
63 $this->relations[$param["arguments"]["rel"]] = new Url($link);
64 }
65 }
66 }
67
68 /**
69 * Receive the link header's parsed relations
70 *
71 * @return array
72 */
73 function getRelations() : array {
74 return $this->relations;
75 }
76
77 /**
78 * Get the URL of the link's "next" relation
79 *
80 * Returns the link's "last" relation if it exists and "next" is not set.
81 *
82 * @return Url
83 */
84 function getNext() {
85 if (isset($this->relations["next"])) {
86 return $this->relations["next"];
87 }
88 if (isset($this->relations["last"])) {
89 return $this->relations["last"];
90 }
91 return null;
92 }
93
94 /**
95 * Get the URL of the link's "prev" relation
96 *
97 * Returns the link's "first" relation if it exists and "prev" is not set.
98 *
99 * @return Url
100 */
101 function getPrev() {
102 if (isset($this->relations["prev"])) {
103 return $this->relations["prev"];
104 }
105 if (isset($this->relations["first"])) {
106 return $this->relations["first"];
107 }
108 return null;
109 }
110
111 /**
112 * Get the URL of the link's "last" relation
113 *
114 * @return Url
115 */
116 function getLast() {
117 if (isset($this->relations["last"])) {
118 return $this->relations["last"];
119 }
120 return null;
121 }
122
123 /**
124 * Get the URL of the link's "first" relation
125 *
126 * @return Url
127 */
128 function getFirst() {
129 if (isset($this->relations["first"])) {
130 return $this->relations["first"];
131 }
132 return null;
133 }
134
135 /**
136 * Get the page sequence of the current link's relation
137 *
138 * @param string $which The relation of which to extract the page
139 * @return int The current page sequence
140 */
141 function getPage($which) {
142 if (($link = $this->{"get$which"}())) {
143 $url = new Url($link, null, 0);
144 $qry = new QueryString($url->query);
145 return $qry->getInt("page", 1);
146 }
147 return 1;
148 }
149 }