PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.5.21
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.5.21
2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 1.7.2 All 33 releases
fluent-booking / vendor / wpfluent / caldav / src / Clients / Client.php

Client.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 1.5.21, at vendor/wpfluent/caldav/src/Clients/Client.php

347 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBooking\Package\CalDav\Clients;
4
5 use Exception;
6 use FluentBooking\Package\CalDav\ICal\Event;
7 use FluentBooking\Package\CalDav\ICal\XmlParser;
8 use FluentBooking\Package\CalDav\Entities\Calendar;
9 use FluentBooking\Framework\Foundation\WPException;
10
11 class Client
12 {
13 use CommonTrait;
14
15 protected $username = null;
16
17 protected $password = null;
18
19 protected $baseUrl = null;
20
21 public function __construct($credentials)
22 {
23 if (!is_array($credentials)) {
24 $credentials = array_combine(
25 ['base_url', 'username', 'password'], func_get_args()
26 );
27 }
28
29 if ($this->validateCredentials($credentials)) {
30 $this->username = $credentials['username'];
31 $this->password = $credentials['password'];
32 $this->baseUrl = rtrim($credentials['base_url'], '/');
33 }
34 }
35
36 public function validateCredentials($credentials)
37 {
38 $isset = isset(
39 $credentials['username'],
40 $credentials['password'],
41 $credentials['base_url']
42 );
43
44 if (!$isset) {
45 throw new Exception('Invalid credentials given.');
46 }
47
48 return true;
49 }
50
51 protected function makeUrl($param = '')
52 {
53 $param = trim($param, '/');
54
55 return "{$this->baseUrl}/{$param}";
56 }
57
58 public function createCalendar($data)
59 {
60 return new Calendar($data, $this);
61 }
62
63 public function getCalendarsInfo($url)
64 {
65 $payload = '<?xml version="1.0" encoding="utf-8"?>
66 <d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/" xmlns:c="urn:ietf:params:xml:ns:caldav">
67 <d:prop>
68 <d:resourcetype />
69 <d:displayname />
70 <cs:getctag />
71 <c:supported-calendar-component-set />
72 </d:prop>
73 </d:propfind>';
74
75 $response = $this->propfind($url, [
76 'payload' => $payload
77 ], ['depth' => 1]);
78
79 $content = wp_remote_retrieve_body($response);
80
81 $list = XmlParser::parse($content);
82
83 $calendars = [];
84
85 foreach ($list as $cal) {
86
87 foreach ($cal['propstat'] as $propstat) {
88
89 if (isset($propstat['status']) && is_array($propstat['status'])) {
90 $okay = str_contains($propstat['status'][0], '200 OK');
91 }
92
93 foreach ($propstat['prop'] as $prop) {
94
95 if ($okay && isset($prop['resourcetype'])) {
96
97 $attrs = [];
98
99 if (isset($prop['supported-calendar-component-set'])) {
100 $sccs = $prop['supported-calendar-component-set'][0];
101
102 foreach ($sccs['comp'] as $key => $value) {
103 $attrs[] = $value['attributers']['name'];
104 }
105 }
106
107 if (
108 array_key_exists('calendar', $prop['resourcetype'][0])
109 && in_array('VEVENT', $attrs)
110 ) {
111 $calendars[] = [
112 'href' => $cal['href'][0],
113 'displayname' => $prop['displayname'][0],
114 'getctag' => $prop['getctag'][0]
115 ];
116 }
117 }
118 }
119 }
120 }
121
122 return array_map(function($calendar) {
123 return new Calendar($calendar, $this);
124 }, $calendars);
125 }
126
127 public function getCalendarInfo($url)
128 {
129 $payload = '<?xml version="1.0" encoding="utf-8" ?>
130 <d:propfind xmlns:d="DAV:" xmlns:cs="http://calendarserver.org/ns/">
131 <d:prop>
132 <d:displayname />
133 <cs:getctag />
134 <d:getetag />
135 </d:prop>
136 </d:propfind>';
137
138 $response = $this->propfind(
139 $url, ['payload' => $payload], ['depth' => 1]
140 );
141
142 $content = wp_remote_retrieve_body($response);
143
144 $content = XmlParser::parse($content);
145
146 $items = [];
147
148 foreach ($content as $key => $item) {
149
150 foreach ($item['propstat'] as $propstatKey => $propstat) {
151
152 if (!str_contains($propstat['status'][0], '200 OK')) {
153 continue;
154 }
155
156 $items[$propstatKey][$key]['href'] = $item['href'][0];
157
158 foreach($propstat as $prop) {
159
160 foreach($prop as $k => $p) {
161
162 if (isset($p['displayname'])) {
163 $items[$propstatKey][$key]['displayname'] = $p['displayname'][0];
164 }
165
166 if (isset($p['getctag'])) {
167 $items[$propstatKey][$key]['getctag'] = $p['getctag'][0];
168 }
169
170 if (isset($p['getetag'])) {
171 $items[$propstatKey][$key]['getetag'] = $p['getetag'][0];
172 }
173 }
174 }
175 }
176
177 }
178
179 $items = reset($items);
180
181 $items = array_merge($items[0], ['etag' => $items[1]]);
182
183 return new Calendar(isset($items[0]) ? $items[0] : $items, $this);
184 }
185
186 public function getEventsFrom($url, $dateRange = [])
187 {
188 $dateFilter = '';
189
190 if (!empty($dateRange)) {
191 $startDate = $dateRange[0];
192 $endDate = $dateRange[1];
193
194 $dateFilter = '<c:time-range start="' . $startDate->format('Ymd\THis\Z') . '" end="' . $endDate->format('Ymd\THis\Z') . '" />';
195 }
196
197 $payload = '<?xml version="1.0" encoding="utf-8" ?>
198 <c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
199 <d:prop>
200 <d:getetag />
201 <c:calendar-data />
202 </d:prop>
203 <c:filter>
204 <c:comp-filter name="VCALENDAR">
205 <c:comp-filter name="VEVENT">'. $dateFilter .'</c:comp-filter>
206 </c:comp-filter>
207 </c:filter>
208 </c:calendar-query>';
209
210 $response = $this->report($url, [
211 'payload' => $payload
212 ], ['depth' => 1]);
213
214 $content = wp_remote_retrieve_body($response);
215
216 return $this->extractReportinformation($content);
217 }
218
219 public function getEventFrom($url)
220 {
221 $response = $this->get($url, [], [
222 'depth' => 1,
223 'Content-Type' => 'application/json'
224 ]);
225
226 $content = wp_remote_retrieve_body($response);
227
228 return [
229 'event' => $this->extractSingleEvent($content),
230 'etag' => wp_remote_retrieve_header($response, 'etag'),
231 'status' => 'HTTP/1.1 200 OK'
232 ];
233 }
234
235 public function addEventTo($url, $payload)
236 {
237 $event = $payload instanceof Event ? $payload : new Event($payload);
238
239 $uid = $event->getUid();
240
241 $url = rtrim($url, '/') . '/'. $uid.'.ics';
242
243 $response = $this->put($url, [
244 'payload' => $event->compile()
245 ], ['Content-Type' => 'text/calendar; charset=utf-8']);
246
247 return $response['response'];
248 }
249
250 public function deleteEvent($url)
251 {
252 // dd($url);
253 $response = $this->delete(
254 $url, [], ['Content-Type' => 'application/json']
255 );
256
257 return $response['response'];
258 }
259
260 public function propfind($url, $args, $headers = [])
261 {
262 return $this->request('PROPFIND', $url, $args, $headers);
263 }
264
265 public function report($url, $args, $headers = [])
266 {
267 return $this->request('REPORT', $url, $args, $headers);
268 }
269
270 public function put($url, $args, $headers = [])
271 {
272 return $this->request('PUT', $url, $args, $headers);
273 }
274
275 public function get($url, $args = [], $headers = [])
276 {
277 return $this->request('GET', $url, $args, $headers);
278 }
279
280 public function delete($url, $args = [], $headers = [])
281 {
282 return $this->request('DELETE', $url, $args, $headers);
283 }
284
285 public function request($method, $url, $args, $headers = [])
286 {
287 $response = $this->sendRequest($method, $url, $args, $headers);
288
289 if (is_wp_error($response)) {
290 throw new WPException($response);
291 } else {
292 $statusCode = wp_remote_retrieve_response_code($response);
293
294 if (intval($statusCode / 100) !== 2) {
295 $this->throwException($statusCode, $response);
296 }
297 }
298
299 return $response;
300 }
301
302 protected function sendRequest($method, $url, $args, $headers)
303 {
304 // if ($method == 'DELETE') dd($url, $this->prepareArgs($method, $args, $headers));
305 return wp_remote_request(
306 $url, $this->prepareArgs($method, $args, $headers)
307 );
308 }
309
310 protected function prepareArgs($method, $args, $headers)
311 {
312 $ns = strtolower(substr(__NAMESPACE__, 0, strpos(__NAMESPACE__, '\\')));
313
314 $args = array_merge($args, [
315 'method' => $method,
316 'headers' => [
317 'User-Agent' => 'wpfluent-' . $ns
318 ]
319 ]);
320
321 if (!isset($headers['Authorization'])) {
322 $headers['Authorization'] = $this->getAuthCredential();
323 }
324
325 $args['headers'] = array_merge($args['headers'], $headers);
326
327 if (isset($args['payload'])) {
328 $args['body'] = $args['payload'];
329 }
330
331 unset($args['payload']);
332
333 return $args;
334 }
335
336 protected function throwException($statusCode, $response)
337 {
338 $message = wp_remote_retrieve_response_message($response);
339
340 if (class_exists($class = "WpOrg\Requests\Exception\Http\Status{$statusCode}")) {
341 throw new $class($message);
342 }
343
344 throw new Exception($message, $statusCode);
345 }
346 }
347