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