1: <?php
2: /*
3: * SimpleID
4: *
5: * Copyright (C) Kelvin Mo 2014-2025
6: *
7: * This program is free software; you can redistribute it and/or
8: * modify it under the terms of the GNU General Public
9: * License as published by the Free Software Foundation; either
10: * version 2 of the License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program; if not, write to the Free
19: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20: *
21: */
22:
23: namespace SimpleID\Protocols\XRDS;
24:
25: /**
26: * A collection of discovered XRDS services.
27: *
28: * The collection can be queried using the {@link getByType()} and
29: * {@link getById()} functions.
30: */
31: class XRDSServices {
32:
33: /** @var array<array<string, mixed>> Array of discovered services */
34: private $services = [];
35:
36: /**
37: * Adds a service.
38: *
39: * @param array<string, mixed> $service the service to add
40: * @param bool $sort whether to sort the services in place
41: * @return void
42: */
43: public function add($service, $sort = true) {
44: $this->services[] = $service;
45: if ($sort) uasort($this->services, '\SimpleID\Protocols\XRDS\XRDSServices::sortByPriority');
46: }
47:
48: /**
49: * Returns the number of services.
50: *
51: * @return int the number of services
52: */
53: public function getLength() {
54: return count($this->services);
55: }
56:
57: /**
58: * Obtains information on discovered services of
59: * a particular type.
60: *
61: * @param string $type the URI of the type of service to obtain
62: * @return array<array<string, mixed>> an array of matching services, or an empty array of no services
63: * match
64: */
65: public function getByType($type) {
66: $matches = [];
67:
68: foreach ($this->services as $service) {
69: foreach ($service['type'] as $service_type) {
70: if ($service_type == $type) $matches[] = $service;
71: }
72: }
73: return $matches;
74: }
75:
76: /**
77: * Obtains information on a discovered service of
78: * a specified ID.
79: *
80: * @param string $id the XML ID of the service in the XRDS document
81: * @return array<string, mixed>|null the matching service, or NULL of no services
82: * are found
83: */
84: public function getById($id) {
85: foreach ($this->services as $service) {
86: if ($service['#id'] == $id) return $service;
87: }
88: return NULL;
89: }
90:
91: /**
92: * Callback function to sort service and URI elements based on priorities
93: * specified in the XRDS document.
94: *
95: * The XRDS specification allows multiple instances of certain elements, such
96: * as Service and URI. The specification allows an attribute called priority
97: * so that the document creator can specify the order the elements should be used.
98: *
99: * @param array<string, mixed> $a
100: * @param array<string, mixed> $b
101: * @return int
102: */
103: static public function sortByPriority($a, $b) {
104: if (!isset($a['#priority']) && !isset($b['#priority'])) return 0;
105:
106: // if #priority is missing, #priority is assumed to be infinity
107: if (!isset($a['#priority'])) return 1;
108: if (!isset($b['#priority'])) return -1;
109:
110: if ($a['#priority'] == $b['#priority']) return 0;
111: return ($a['#priority'] < $b['#priority']) ? -1 : 1;
112: }
113: }
114:
115: ?>
116: