PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 3.33
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v3.33
3.36 3.35 3.34 3.33 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.40 2.41 2.42 2.43 2.44 All 141 releases
photonic / Platforms / Flickr.php

Flickr.php in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 3.33, at Platforms/Flickr.php

1,278 lines 49.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Photonic_Plugin\Platforms;
4
5 use Photonic_Plugin\Components\Album_List;
6 use Photonic_Plugin\Components\Collection;
7 use Photonic_Plugin\Components\Error;
8 use Photonic_Plugin\Components\Header;
9 use Photonic_Plugin\Components\Pagination;
10 use Photonic_Plugin\Components\Photo_List;
11 use Photonic_Plugin\Components\Single_Photo;
12 use Photonic_Plugin\Core\Photonic;
13 use Photonic_Plugin\Components\Album;
14 use Photonic_Plugin\Components\Photo;
15 use WP_Error;
16 use WpOrg\Requests\Hooks;
17 use WpOrg\Requests\Requests;
18
19 require_once 'OAuth1.php';
20 require_once 'Level_One_Module.php';
21 require_once 'Level_Two_Module.php';
22 require_once 'Pageable.php';
23 require_once PHOTONIC_PATH . '/Components/Collection.php';
24
25 /**
26 * ## Main Module for Flickr Galleries
27 *
28 * This module inherits from the Photonic_Plugin\Platforms\Base module. Flickr supports **OAuth1 authentication**.
29 *
30 * Flickr supports 4 levels of galleries:
31 * - Individual photos (Level 0)
32 * - Photosets / Individual Albums / Individual Galleries (Level 1)
33 * - All or selected Albums and Galleries (Level 2)
34 * - Collections (Level 3)
35 *
36 * All galleries can be laid out using any of the layout options.
37 */
38 class Flickr extends OAuth1 implements Level_One_Module, Level_Two_Module, Pageable {
39 private static $instance = null;
40
41 protected function __construct() {
42 parent::__construct();
43 global $photonic_flickr_api_key, $photonic_flickr_api_secret, $photonic_flickr_disable_title_link, $photonic_flickr_access_token, $photonic_flickr_token_secret;
44 $this->api_key = trim($photonic_flickr_api_key);
45 $this->api_secret = trim($photonic_flickr_api_secret);
46 $this->token = trim($photonic_flickr_access_token);
47 $this->token_secret = trim($photonic_flickr_token_secret);
48
49 $this->provider = 'flickr';
50 $this->link_lightbox_title = empty($photonic_flickr_disable_title_link);
51 $this->base_url = 'https://api.flickr.com/services/rest/';
52
53 $this->doc_links = [
54 'general' => 'https://aquoid.com/plugins/photonic/flickr/',
55 'photo' => 'https://aquoid.com/plugins/photonic/flickr/flickr-photo',
56 'photos' => 'https://aquoid.com/plugins/photonic/flickr/flickr-photos/',
57 'photosets' => 'https://aquoid.com/plugins/photonic/flickr/flickr-photosets/',
58 'galleries' => 'https://aquoid.com/plugins/photonic/flickr/flickr-galleries/',
59 'collections' => 'https://aquoid.com/plugins/photonic/flickr/flickr-collections/',
60 'auth' => 'https://aquoid.com/plugins/photonic/flickr/flickr-authentication',
61 ];
62
63 $this->set_oauth_done();
64 }
65
66 /**
67 * A very flexible function to display a user's photos from Flickr. This makes use of the Flickr API, hence it requires the user's API key.
68 * The API key is defined in the options. The function makes use of three different APIs:
69 * 1. <a href='https://www.flickr.com/services/api/flickr.photos.search.html'>flickr.photos.search</a> - for retrieving photos based on search critiera
70 * 2. <a href='https://www.flickr.com/services/api/flickr.photosets.getPhotos.html'>flickr.photosets.getPhotos</a> - for retrieving photo sets
71 * 3. <a href='https://www.flickr.com/services/api/flickr.galleries.getPhotos.html'>flickr.galleries.getPhotos</a> - for retrieving galleries
72 *
73 * The following short-code parameters are supported:
74 * All
75 * - per_page: number of photos to display
76 * - view: photos | collections | galleries | photosets, displays hierarchically if user_id is passed
77 * Photosets
78 * - photoset_id
79 * Galleries
80 * - gallery_id
81 * Photos
82 * - user_id: can be obtained from the Helpers page
83 * - tags: comma-separated list of tags
84 * - tag_mode: any | all, tells whether any tag should be used or all
85 * - text: string for text search
86 * - sort: date-posted-desc | date-posted-asc | date-taken-asc | date-taken-desc | interestingness-desc | interestingness-asc | relevance
87 * - group_id: group id for which photos will be displayed
88 *
89 * @param array $attr
90 * @return array
91 * @since 1.02
92 */
93 public function get_gallery_images($attr = []): array {
94 global $photonic_flickr_title_caption, $photonic_flickr_media, $photonic_flickr_default_user,
95 $photonic_flickr_thumb_size, $photonic_flickr_main_size, $photonic_flickr_tile_size, $photonic_flickr_video_size;
96
97 $this->push_to_stack('Get gallery images');
98 $attr = array_merge(
99 $this->common_parameters,
100 [
101 // Common overrides ...
102 'caption' => $photonic_flickr_title_caption,
103 'thumb_size' => $photonic_flickr_thumb_size,
104 'main_size' => $photonic_flickr_main_size,
105 'tile_size' => $photonic_flickr_tile_size,
106 'video_size' => $photonic_flickr_video_size,
107
108 // Flickr-Specific ...
109 // 'view' => 'photos' // photos | collections | galleries | photosets: if only a user id is passed, what should be displayed?
110 'privacy_filter' => '',
111 'count' => 500,
112 'page' => 1,
113 'paginate' => false,
114 'collections_display' => 'expanded',
115 'user_id' => $photonic_flickr_default_user,
116 'collection_id' => '',
117 'photoset_id' => '',
118 'gallery_id' => '',
119 'photo_id' => '',
120 'media' => $photonic_flickr_media,
121 ],
122 $attr
123 );
124 $attr = array_map('trim', $attr);
125
126 if (empty($this->api_key)) {
127 $this->pop_from_stack();
128 return [new Error(esc_html__('Flickr API Key not defined.', 'photonic') . Photonic::doc_link($this->doc_links['general']))];
129 }
130
131 $query_urls = [];
132 $flickr_params = [];
133
134 $flickr_params['extras'] = 'description,owner_name,date_upload,date_taken,url_c,c_dims,url_h,h_dims,url_k,k_dims,url_o,o_dims,url_b,b_dims,url_z,z_dims,url_n,n_dims,url_m,m_dims,url_q,q_dims,url_t,t_dims,url_s,s_dims,media';
135 $flickr_params['primary_photo_extras'] = 'url_c,c_dims,url_h,h_dims,url_k,k_dims,url_o,o_dims,url_b,b_dims,url_z,z_dims,url_n,n_dims,url_m,m_dims,url_q,q_dims,url_t,t_dims,url_s,s_dims,media';
136
137 $attr['iterate_level_3'] = 'expanded' === $attr['collections_display'];
138 $attr['per_page'] = empty($attr['per_page']) ? $attr['count'] : $attr['per_page'];
139 $attr['photo_count'] = empty($attr['photo_count']) ? $attr['per_page'] : $attr['photo_count'];
140
141 $attr['overlay_size'] = empty($attr['overlay_size']) ? $attr['thumb_size'] : $attr['overlay_size'];
142 $attr['overlay_video_size'] = empty($attr['overlay_video_size']) ? $attr['video_size'] : $attr['overlay_video_size'];
143
144 if (empty($attr['group_id'])) {
145 $user = empty($attr['user_id']) ? $photonic_flickr_default_user : $attr['user_id'];
146 }
147
148 if (isset($attr['view']) && 'photos' === $attr['view'] && !empty($attr['group_id']) && empty($attr['photoset_id'])) {
149 $query_urls[] = $this->base_url . '?method=flickr.photos.search';
150 }
151 elseif (isset($attr['view']) && 'photo' === $attr['view'] && !empty($attr['photo_id'])) {
152 $query_urls[] = $this->base_url . '?method=flickr.photos.getInfo';
153 }
154 elseif (isset($attr['view']) && (!empty($user))) {
155 switch ($attr['view']) {
156 case 'collections':
157 if (empty($attr['collection_id'])) {
158 $collections = $this->get_collection_list($user, '', $attr['filter']);
159 foreach ($collections as $collection) {
160 $query_urls[] = $this->base_url . '?method=flickr.collections.getTree&collection_id=' . $collection['id'];
161 }
162 }
163 break;
164
165 case 'galleries':
166 if (empty($attr['gallery_id'])) {
167 $query_urls[] = $this->base_url . '?method=flickr.galleries.getList';
168 }
169 break;
170
171 case 'photosets':
172 if (empty($attr['photoset_id'])) {
173 $query_urls[] = $this->base_url . '?method=flickr.photosets.getList';
174 }
175 break;
176
177 case 'photo':
178 if (!empty($attr['photo_id'])) {
179 $query_urls[] = $this->base_url . '?method=flickr.photos.getInfo';
180 }
181 break;
182
183 case 'photos':
184 default:
185 if (empty($attr['photoset_id']) && empty($attr['gallery_id']) && empty($attr['collection_id']) && empty($attr['photo_id'])) {
186 $query_urls[] = $this->base_url . '?method=flickr.photos.search';
187 }
188 break;
189 }
190 }
191
192 // Collection > galleries > photosets
193 if (!empty($attr['collection_id'])) {
194 $collections = $this->get_collection_list($user, $attr['collection_id']);
195 $attr['iterate_level_3'] = true;
196 foreach ($collections as $collection) {
197 $query_urls[] = $this->base_url . '?method=flickr.collections.getTree&collection_id=' . $collection['id'];
198 }
199 }
200 elseif (!empty($attr['gallery_id'])) {
201 if (empty($attr['gallery_id_computed'])) {
202 if (empty($user)) {
203 $this->pop_from_stack();
204 return [new Error(esc_html__('User id or default user is required for displaying a single gallery', 'photonic'))];
205 }
206
207 $this->push_to_stack("Gallery list (user '$user')");
208 $feed = $this->make_call($this->base_url . '?method=flickr.galleries.getList', $flickr_params);
209
210 if (!is_wp_error($feed)) {
211 if (200 === $feed['response']['code']) {
212 $feed = $feed['body'];
213 $feed = json_decode($feed);
214 if (isset($feed->galleries)) {
215 $galleries = $feed->galleries;
216 $galleries = $galleries->gallery;
217 if (is_array($galleries) && count($galleries) > 0) {
218 $gallery = $galleries[0];
219 $global_dbid = $gallery->id;
220 $global_dbid = substr($global_dbid, 0, stripos($global_dbid, '-'));
221 }
222 }
223 }
224 }
225
226 if (isset($global_dbid)) {
227 $attr['gallery_id'] = $global_dbid . '-' . $attr['gallery_id'];
228 }
229 $this->pop_from_stack();
230 }
231 $query_urls[] = $this->base_url . '?method=flickr.galleries.getInfo';
232 $query_urls[] = $this->base_url . '?method=flickr.galleries.getPhotos';
233 }
234 elseif (!empty($attr['photoset_id'])) {
235 $query_urls[] = $this->base_url . '?method=flickr.photosets.getInfo';
236 $query_urls[] = $this->base_url . '?method=flickr.photosets.getPhotos';
237 }
238 elseif (empty($attr['photo_id']) && empty($user) && empty($attr['group_id'])) {
239 $query_urls[] = $this->base_url . '?method=flickr.photos.search';
240 }
241
242 if (!empty($user) && empty($attr['photoset_id']) && empty($attr['photo_id'])) {
243 $flickr_params['user_id'] = $user;
244 }
245
246 if (!empty($attr['collection_id'])) {
247 $flickr_params['collection_id'] = $attr['collection_id'];
248 }
249 elseif (!empty($attr['gallery_id'])) {
250 $flickr_params['gallery_id'] = $attr['gallery_id'];
251 }
252 elseif (!empty($attr['photoset_id'])) {
253 $flickr_params['photoset_id'] = $attr['photoset_id'];
254 }
255 elseif (!empty($attr['photo_id'])) {
256 $flickr_params['photo_id'] = $attr['photo_id'];
257 }
258
259 if (!empty($attr['tags'])) {
260 $flickr_params['tags'] = $attr['tags'];
261 }
262
263 if (!empty($attr['tag_mode'])) {
264 $flickr_params['tag_mode'] = $attr['tag_mode'];
265 }
266
267 if (!empty($attr['text'])) {
268 $flickr_params['text'] = $attr['text'];
269 }
270
271 if (!empty($attr['sort'])) {
272 $flickr_params['sort'] = $attr['sort'];
273 }
274
275 if (!empty($attr['group_id'])) {
276 $flickr_params['group_id'] = $attr['group_id'];
277 }
278
279 if (!empty($attr['per_page'])) {
280 $flickr_params['per_page'] = $attr['per_page'];
281 }
282
283 if (!empty($attr['page'])) {
284 $flickr_params['page'] = $attr['page'];
285 }
286
287 if (!empty($attr['privacy_filter'])) {
288 $flickr_params['privacy_filter'] = $attr['privacy_filter'];
289 }
290
291 if (!empty($attr['media'])) {
292 $flickr_params['media'] = $attr['media'];
293 }
294
295 $header_display = $this->get_header_display($attr);
296 $attr['header_display'] = $header_display;
297
298 $components = [];
299 foreach ($query_urls as $query_url) {
300 $method = 'flickr.photos.getInfo';
301 $iterator = [];
302 if (is_array($query_url)) {
303 $iterator = $query_url;
304 }
305 else {
306 $iterator[] = $query_url;
307 }
308
309 foreach ($iterator as $nested_query_url) {
310 $this->push_to_stack("Nested call $method");
311 $method = wp_parse_args(substr($nested_query_url, stripos($nested_query_url, '?') + 1));
312 $method = $method['method'];
313 $response = $this->make_call($nested_query_url, $flickr_params);
314 $flickr_params['method'] = $method;
315
316 $processed_response = $this->process_query($response, $flickr_params, $attr);
317 $components = array_merge($components, $processed_response);
318 $this->pop_from_stack();
319 }
320 }
321 $this->pop_from_stack();
322
323 if (!empty($this->stack_trace[$this->gallery_index])) {
324 $components[] = $this->stack_trace[$this->gallery_index];
325 }
326 return $components;
327 }
328
329 private function make_call($query, $flickr_params) {
330 $params = substr($query, strlen($this->base_url));
331 if (strlen($params) > 1) {
332 $params = substr($params, 1);
333 }
334 $params = Base::parse_parameters($params);
335 $params['format'] = 'json';
336 $params['nojsoncallback'] = 1;
337 $params['api_key'] = $this->api_key;
338
339 $params = array_merge($flickr_params, $params);
340
341 // We only worry about signing the call if the authentication is done. Otherwise we just show what is available.
342 if ($this->oauth_done) {
343 $signed_args = $this->sign_call($this->base_url, 'GET', $params);
344 $params = $signed_args;
345 }
346
347 $this->push_to_stack("Make call ({$params['method']})");
348 $response = Photonic::http($this->base_url, 'GET', $params, $this->user_agent);
349 $this->pop_from_stack();
350 return $response;
351 }
352
353 /**
354 * Retrieves a list of collection objects for a given user. This first invokes the web-service, then iterates through the collections returned.
355 * For each collection returned it recursively looks for nested collections and sets.
356 *
357 * @param $user_id
358 * @param string $collection_id
359 * @param string $filters
360 * @return array
361 */
362 private function get_collection_list($user_id, $collection_id = '', $filters = ''): array {
363 $this->push_to_stack("Collection list (collection id '$collection_id')");
364 $query = $this->base_url . '?method=flickr.collections.getTree';
365 $flickr_params = [];
366 if (!empty($collection_id)) {
367 $flickr_params['collection_id'] = $collection_id;
368 }
369 if (!empty($user_id)) {
370 $flickr_params['user_id'] = $user_id;
371 }
372
373 $collection_list = [];
374 if (!empty($filters)) {
375 $collection_list = explode(',', $filters);
376 }
377
378 $feed = $this->make_call($query, $flickr_params);
379 if (!is_wp_error($feed) && 200 === $feed['response']['code']) {
380 $feed = $feed['body'];
381 $feed = json_decode($feed);
382 if ('ok' === $feed->stat) {
383 $collections = $feed->collections;
384 $collections = $collections->collection;
385 $ret = [];
386 $processed = [];
387 foreach ($collections as $collection) {
388 if (isset($collection->id)) {
389 if (!in_array($collection->id, $processed, true)) {
390 $iterative = $this->get_nested_collections($collection, $processed);
391 $ret = array_merge($ret, $iterative);
392 }
393 }
394 }
395
396 $filtered_ret = [];
397 if (!empty($collection_list)) {
398 foreach ($ret as $collection) {
399 if (in_array($collection['id'], $collection_list, true)) {
400 $filtered_ret[] = $collection;
401 }
402 }
403 $this->pop_from_stack();
404 return $filtered_ret;
405 }
406
407 $this->pop_from_stack();
408 return $ret;
409 }
410 }
411 $this->pop_from_stack();
412 return [];
413 }
414
415 /**
416 * Goes through a Flickr collection and recursively fetches all sets and other collections within it. This is returned as
417 * a flattened array.
418 *
419 * @param $collection
420 * @param $processed
421 * @return array
422 */
423 private function get_nested_collections($collection, &$processed): array {
424 $id = (string) ($collection->id ?? '');
425 if (in_array($id, $processed, true)) {
426 return [];
427 }
428
429 $processed[] = $id;
430 $id = substr($id, strpos($id, '-') + 1);
431 $title = wp_kses_post($collection->title ?? '');
432 $description = wp_kses_post($collection->description ?? '');
433 $thumb = esc_url($collection->iconsmall ?? ($collection->iconlarge ?? ''));
434 $thumb = ('/images/collection_default_l.gif' === $thumb || '/images/collection_default_s.gif' === $thumb) ? 'https://www.flickr.com' . $thumb : $thumb;
435
436 $ret = [];
437
438 if (isset($collection->set)) {
439 $inner_sets = $collection->set;
440 $sets = [];
441 if (count($inner_sets) > 0) {
442 foreach ($inner_sets as $inner_set) {
443 $sets[] = [
444 'id' => wp_kses_post($inner_set->id),
445 'title' => wp_kses_post($inner_set->title),
446 'description' => wp_kses_post($inner_set->description),
447 ];
448 }
449 }
450
451 $ret[] = [
452 'id' => $id,
453 'title' => $title,
454 'description' => $description,
455 'thumb' => $thumb,
456 'sets' => $sets,
457 ];
458 }
459
460 if (isset($collection->collection)) {
461 $inner_collections = $collection->collection;
462 if (count($inner_collections) > 0) {
463 foreach ($inner_collections as $inner_collection) {
464 $inner_ret = $this->get_nested_collections($inner_collection, $processed);
465 $ret = array_merge($ret, $inner_ret);
466 }
467 }
468 }
469 return $ret;
470 }
471
472 private function process_query($response, $flickr_params, $short_code = []): array {
473 $this->push_to_stack('Process response');
474
475 $filter_list = [];
476 if (!empty($short_code['filter'])) {
477 $filter_list = explode(',', $short_code['filter']);
478 }
479
480 $components = [];
481 if (!is_wp_error($response)) {
482 if (200 === $response['response']['code']) {
483 $body = $response['body'];
484 $body = json_decode($body);
485 switch ($flickr_params['method']) {
486 case 'flickr.photos.getInfo':
487 if (isset($body->photo)) {
488 $photo = $body->photo;
489 $components[] = $this->get_single_photo($photo, $short_code, $flickr_params);
490 }
491 break;
492
493 case 'flickr.photos.search':
494 if (isset($body->photos) && isset($body->photos->photo)) {
495 $photos = $body->photos->photo;
496 $components[] = $this->get_photo_list($photos, 'stream', $flickr_params, $short_code, $this->get_pagination($body->photos));
497 }
498 break;
499
500 case 'flickr.photosets.getInfo':
501 if (isset($body->photoset)) {
502 $photoset = $body->photoset;
503 $components[] = $this->get_photoset_header($photoset, $short_code);
504 }
505 break;
506
507 case 'flickr.photosets.getPhotos':
508 if (isset($body->photoset)) {
509 $photoset = $body->photoset;
510 if (isset($photoset->photo) && isset($photoset->owner)) {
511 $photos = $photoset->photo;
512 $options = [];
513 if (isset($photoset->owner)) {
514 $options['owner'] = $photoset->owner;
515 }
516 $components[] = $this->get_photo_list($photos, 'set', $flickr_params, $short_code, $this->get_pagination($photoset), $options);
517 }
518 }
519 break;
520
521 case 'flickr.photosets.getList':
522 if (isset($body->photosets)) {
523 $photosets = $body->photosets;
524 $components[] = $this->get_photoset_list($photosets, $filter_list, $short_code);
525 }
526 break;
527
528 case 'flickr.galleries.getInfo':
529 if (isset($body->gallery)) {
530 $gallery = $body->gallery;
531 $components[] = $this->get_gallery_header($gallery, $short_code);
532 }
533 break;
534
535 case 'flickr.galleries.getPhotos':
536 if (isset($body->photos)) {
537 $photos = $body->photos;
538 if (isset($photos->photo)) {
539 $photos = $photos->photo;
540 $components[] = $this->get_photo_list($photos, 'gallery', $flickr_params, $short_code, $this->get_pagination($body->photos));
541 }
542 }
543 break;
544
545 case 'flickr.galleries.getList':
546 if (isset($body->galleries)) {
547 $galleries = $body->galleries;
548 $components[] = $this->get_gallery_list($galleries, $filter_list, $short_code);
549 }
550 break;
551
552 case 'flickr.collections.getTree':
553 if (isset($body->collections)) {
554 $collections = $body->collections;
555 $components[] = $this->get_collections($collections, $short_code);
556 }
557 break;
558 }
559 }
560 }
561 else {
562 $this->pop_from_stack();
563 return [new Error($this->wp_error_message($response))];
564 }
565
566 $this->pop_from_stack();
567 return $components;
568 }
569
570 /**
571 * Prints a single photo with the title as an <h3> and the caption as the image caption.
572 *
573 * @param $photo
574 * @param $short_code
575 * @param $flickr_params
576 * @return Single_Photo
577 */
578 public function get_single_photo($photo, $short_code, $flickr_params): Single_Photo {
579 $main_size = 'none' === $short_code['main_size'] ? '' : $short_code['main_size'];
580 $main_image = 'https://farm' . $photo->farm . '.staticflickr.com/' . $photo->server . '/' . (!empty($photo->primary) ? $photo->primary : $photo->id) . '_' . $photo->secret . '_z.jpg';
581
582 $size_response = $this->make_call($this->base_url . '?method=flickr.photos.getSizes&photo_id=' . $photo->id, $flickr_params);
583 if (!is_wp_error($size_response) && 200 === $size_response['response']['code']) {
584 $size_response = $size_response['body'];
585 $size_response = json_decode($size_response);
586 if ('ok' === $size_response->stat) {
587 $size_response = $size_response->sizes;
588 $size_response = $size_response->size;
589 if (is_array($size_response)) {
590 $sizes = [
591 'o' => 'Original',
592 'k' => 'Large 2048',
593 'h' => 'Large 1600',
594 'b' => 'Large',
595 'c' => 'Medium 800',
596 'z' => 'Medium 640',
597 '' => 'Medium',
598 'n' => 'Small 320',
599 'm' => 'Small',
600 'q' => 'Large Square',
601 't' => 'Thumbnail',
602 's' => 'Square',
603 ];
604
605 $max_to_min = array_keys($sizes);
606
607 $pos = array_search($main_size, $max_to_min, true);
608 $count = count($max_to_min);
609 $match_found = false;
610 for ($idx = $pos; $idx < $count; $idx++) {
611 foreach ($size_response as $flickr_size) {
612 if ($flickr_size->label === $sizes[$max_to_min[$idx]]) {
613 $main_image = $flickr_size->source;
614 $match_found = true;
615 break;
616 }
617 }
618 if ($match_found) {
619 break;
620 }
621 }
622 }
623 }
624 }
625
626 return new Single_Photo(
627 $main_image,
628 (isset($photo->urls) && isset($photo->urls->url) && count($photo->urls->url) > 0) ? esc_url($photo->urls->url[0]->_content) : '',
629 isset($photo->title) ? wp_kses_post($photo->title->_content) : '',
630 isset($photo->description) ? wp_kses_post($photo->description->_content) : ''
631 );
632 }
633
634 /**
635 * Prints thumbnails for all photos returned in a query. This is used for printing the results of a search, tag, photoset or gallery.
636 * The photos may be printed in a local, modal, lightbox or template location.
637 *
638 * @param $photos
639 * @param string $parent
640 * @param $flickr_params
641 * @param $short_code
642 * @param Pagination $pagination
643 * @param array $options
644 * @return Photo_List
645 */
646 private function get_photo_list($photos, $parent, $flickr_params, $short_code, $pagination, $options = []): Photo_List {
647 global $photonic_flickr_photo_title_display, $photonic_flickr_photo_pop_title_display;
648 global $photonic_flickr_photos_per_row_constraint, $photonic_flickr_photos_constrain_by_count;
649
650 if ('local' === $short_code['display']) {
651 $title_position = $photonic_flickr_photo_title_display;
652 $row_constraints = ['constraint-type' => $photonic_flickr_photos_per_row_constraint, 'count' => $photonic_flickr_photos_constrain_by_count];
653 }
654 else {
655 $title_position = $photonic_flickr_photo_pop_title_display;
656 $row_constraints = ['constraint-type' => 'padding'];
657 }
658 $photo_objects = $this->build_level_1_objects($photos, $short_code, $flickr_params, array_merge(['parent' => $parent], $options));
659
660 $photo_list = new Photo_List($short_code);
661 $photo_list->photos = $photo_objects;
662 $photo_list->title_position = $title_position;
663 $photo_list->row_constraints = $row_constraints;
664 $photo_list->parent = $parent;
665 $photo_list->pagination = $pagination;
666
667 return $photo_list;
668 }
669
670 private function find_largest_image($photo, $size = 'o', &$dimensions = []): string {
671 // $max_to_min = ['o','k','h','b','c'];
672 $max_to_min = ['o', 'k', 'h', 'b', 'c', 'z', 'm', 'n', 's', 'q', 't'];
673 if ('' === $size) {
674 $size = 'm';
675 }
676
677 $pos = array_search($size, $max_to_min, true);
678 if (false !== $pos) {
679 $count = count($max_to_min);
680 for ($idx = $pos; $idx < $count; $idx++) {
681 $value = $max_to_min[$idx];
682 if (isset($photo->{'url_' . $value})) {
683 $dimensions['w'] = $photo->{'width_' . $value};
684 $dimensions['h'] = $photo->{'height_' . $value};
685 return esc_url($photo->{'url_' . $value});
686 }
687 elseif (isset($photo->primary_photo_extras) && isset($photo->primary_photo_extras->{'url_' . $value})) {
688 $dimensions['w'] = $photo->primary_photo_extras->{'width_' . $value};
689 $dimensions['h'] = $photo->primary_photo_extras->{'height_' . $value};
690 return esc_url($photo->primary_photo_extras->{'url_' . $value});
691 }
692 }
693 }
694
695 if (isset($photo->width_z) && isset($photo->height_z)) {
696 $dimensions['w'] = $photo->width_z;
697 $dimensions['h'] = $photo->height_z;
698 }
699 return esc_url('https://farm' . $photo->farm . '.staticflickr.com/' . $photo->server . '/' . (!empty($photo->primary) ? $photo->primary : $photo->id) . '_' . $photo->secret . '_z.jpg');
700 }
701
702 private function find_largest_video_thumb(&$photo_struct, $current_sizes, $shortcode_sizes) {
703 $video_sizes = [
704 'o' => 'Original',
705 'k' => 'Large 2048',
706 'h' => 'Large 1600',
707 'b' => 'Large',
708 'c' => 'Medium 800',
709 'z' => 'Medium 640',
710 '' => 'Medium',
711 'n' => 'Small 320',
712 'm' => 'Small',
713 'q' => 'Large Square',
714 't' => 'Thumbnail',
715 's' => 'Square',
716 ];
717
718 $max_to_min = array_keys($video_sizes);
719 foreach ($shortcode_sizes as $type => $size) {
720 $match_found = false;
721 $pos = array_search($size, $max_to_min, true);
722 $count = count($max_to_min);
723 for ($idx = $pos; $idx < $count; $idx++) {
724 foreach ($current_sizes as $flickr_size) {
725 if ($flickr_size->label === $video_sizes[$max_to_min[$idx]]) {
726 $photo_struct->{$type} = $flickr_size->source;
727 $match_found = true;
728 break;
729 }
730 }
731 if ($match_found) {
732 break;
733 }
734 }
735 }
736 }
737
738 public function build_level_1_objects($response, array $short_code, $module_parameters = [], $options = []): array {
739 $photo_objects = [];
740 $video_size = in_array(Photonic::$library, ['baguettebox', 'colorbox', 'fancybox', 'fancybox2', 'fancybox3', 'featherlight', 'glightbox', 'lightgallery', 'magnific', 'photoswipe', 'spotlight', 'swipebox', 'venobox'], true) ? $short_code['video_size'] : 'Video Player';
741 // $video_size = $short_code['video_size'];
742
743 $main_size = sanitize_text_field('none' === $short_code['main_size'] ? '' : $short_code['main_size']);
744 $tile_size = sanitize_text_field((empty($short_code['tile_size']) || 'same' === $short_code['tile_size']) ? $main_size : ('none' === $short_code['tile_size'] ? '' : $short_code['tile_size']));
745
746 foreach ($response as $photo) {
747 $photonic_photo = new Photo();
748
749 $photonic_photo->thumbnail = esc_url($photo->{'url_' . $short_code['thumb_size']} ?? ('https://farm' . $photo->farm . '.staticflickr.com/' . $photo->server . '/' . $photo->id . '_' . $photo->secret . '_' . $short_code['thumb_size'] . '.jpg'));
750 $photonic_photo->thumb_size = [
751 'w' => 's' === $short_code['thumb_size'] ? 75 : ('q' === $short_code['thumb_size'] ? 150 : $photo->{'width_' . $short_code['thumb_size']}),
752 'h' => 's' === $short_code['thumb_size'] ? 75 : ('q' === $short_code['thumb_size'] ? 150 : $photo->{'height_' . $short_code['thumb_size']}),
753 ];
754
755 $main_dim = [];
756 $photonic_photo->main_image = $this->find_largest_image($photo, $main_size, $main_dim);
757 $photonic_photo->main_size = $main_dim;
758
759 $download = $this->find_largest_image($photo);
760 $photonic_photo->download = substr($download, 0, strlen($download) - 4) . '_d' . substr($download, -4);
761
762 $tile_dim = $main_dim;
763 $photonic_photo->tile_image = $tile_size === $main_size ? $photonic_photo->main_image : $this->find_largest_image($photo, $tile_size, $tile_dim);
764 $photonic_photo->tile_size = $tile_dim;
765 $photonic_photo->alt_title = wp_kses_post($photo->title);
766
767 $owner = '';
768 if (!empty($options['owner'])) {
769 $owner = $options['owner'];
770 }
771 elseif (isset($photo->owner)) {
772 $owner = $photo->owner;
773 }
774 elseif (isset($photo->ownername)) {
775 $owner = $photo->ownername;
776 }
777
778 $specific = '';
779 if ('set' === $options['parent'] && !empty($module_parameters['photoset_id'])) {
780 $specific = '/in/set-' . $module_parameters['photoset_id'];
781 }
782 $url = esc_url("https://www.flickr.com/photos/" . $owner . "/" . $photo->id . $specific);
783 $photonic_photo->main_page = $url;
784
785 $title = wp_kses_post($photo->title);
786 $photonic_photo->title = $title;
787
788 if (isset($photo->description)) {
789 $photonic_photo->description = $photo->description->_content;
790 }
791 else {
792 $photonic_photo->description = '';
793 }
794
795 if (isset($photo->datetaken)) {
796 $photonic_photo->taken_on = sanitize_text_field($photo->datetaken);
797 }
798
799 if (isset($photo->dateupload)) {
800 $photonic_photo->uploaded_on = sanitize_text_field($photo->dateupload);
801 }
802
803 if (!empty($photo->media) && 'video' === $photo->media) {
804 $video_response = $this->make_call($this->base_url . '?method=flickr.photos.getSizes&photo_id=' . $photo->id, $module_parameters);
805 if (!is_wp_error($video_response) && 200 === $video_response['response']['code']) {
806 $video_response = $video_response['body'];
807 $video_response = json_decode($video_response);
808 if ('ok' === $video_response->stat) {
809 $video_response = $video_response->sizes;
810 $video_response = $video_response->size;
811 if (is_array($video_response)) {
812 $this->find_largest_video_thumb(
813 $photonic_photo,
814 $video_response,
815 [
816 'main_image' => $main_size,
817 'tile_image' => $tile_size,
818 'thumbnail' => $short_code['thumb_size'],
819 ]
820 );
821
822 foreach ($video_response as $size) {
823 if ($size->label !== $video_size) {
824 continue;
825 }
826 else {
827 $photonic_photo->video = $size->source;
828 $photonic_photo->mime = 'video/mp4';
829 break;
830 }
831 }
832 }
833 }
834 }
835 }
836
837 $photonic_photo->id = $photo->id;
838
839 $photo_objects[] = $photonic_photo;
840 }
841
842 return $photo_objects;
843 }
844
845 public function build_level_2_objects($objects_or_response, array $short_code, array $filter_list = [], array &$options = [], ?Pagination &$pagination = null): array {
846 global $photonic_gallery_template_page;
847
848 $main_size = sanitize_text_field('none' === $short_code['main_size'] ? '' : $short_code['main_size']);
849 $tile_size = sanitize_text_field((empty($short_code['tile_size']) || 'same' === $short_code['tile_size']) ? $main_size : ('none' === $short_code['tile_size'] ? '' : $short_code['tile_size']));
850
851 $objects = [];
852
853 $type = $options['type'];
854 foreach ($objects_or_response as $flickr_object) {
855 if (!empty($filter_list) &&
856 (('photoset' === $type && ((!in_array($flickr_object->id, $filter_list, true) && strtolower($short_code['filter_type']) !== 'exclude') ||
857 (in_array($flickr_object->id, $filter_list, true) && strtolower($short_code['filter_type']) === 'exclude'))) ||
858 ('gallery' === $type && ((!in_array(substr($flickr_object->id, stripos($flickr_object->id, '-') + 1), $filter_list, true) && strtolower($short_code['filter_type']) !== 'exclude') ||
859 (in_array(substr($flickr_object->id, stripos($flickr_object->id, '-') + 1), $filter_list, true) && strtolower($short_code['filter_type']) === 'exclude'))))) {
860 continue;
861 }
862
863 $photonic_album = new Album();
864
865 $internal_short_code = $short_code;
866 unset($internal_short_code['collection_id']);
867 $internal_short_code['layout'] = empty($short_code['photo_layout']) ? $short_code['layout'] : $short_code['photo_layout'];
868
869 $photonic_album->id = $flickr_object->id;
870 $photonic_album->title = wp_kses_post($flickr_object->title->_content);
871 $photonic_album->description = wp_kses_post($flickr_object->description->_content);
872
873 if ('gallery' === $type) {
874 $photonic_album->thumbnail = esc_url($flickr_object->primary_photo_extras->{'url_' . $short_code['thumb_size']} ?? ("https://farm" . $flickr_object->primary_photo_farm . ".staticflickr.com/" . $flickr_object->primary_photo_server . "/" . $flickr_object->primary_photo_id . "_" . $flickr_object->primary_photo_secret . "_" . $short_code['thumb_size'] . ".jpg"));
875 $photonic_album->tile_image = esc_url($flickr_object->primary_photo_extras->{'url_' . $tile_size} ?? ("https://farm" . $flickr_object->primary_photo_farm . ".staticflickr.com/" . $flickr_object->primary_photo_server . "/" . $flickr_object->primary_photo_id . "_" . $flickr_object->primary_photo_secret . '_' . $tile_size . ".jpg"));
876 $photonic_album->tile_size = [
877 'w' => 's' === $tile_size ? 75 : ('q' === $tile_size ? 150 : $flickr_object->primary_photo_extras->{'width_' . $tile_size}),
878 'h' => 's' === $tile_size ? 75 : ('q' === $tile_size ? 150 : $flickr_object->primary_photo_extras->{'height_' . $tile_size}),
879 ];
880
881 $photonic_album->main_page = esc_url($flickr_object->url);
882 $photonic_album->counter = $flickr_object->count_photos;
883 $photonic_album->classes = ["photonic-flickr-gallery-thumb-user-{$short_code['user_id']}"];
884
885 $internal_short_code['view'] = 'gallery';
886 $internal_short_code['gallery_id'] = $flickr_object->id;
887 }
888 elseif ('photoset' === $type) {
889 $photonic_album->thumbnail = esc_url($flickr_object->primary_photo_extras->{'url_' . $short_code['thumb_size']} ?? ("https://farm" . $flickr_object->farm . ".staticflickr.com/" . $flickr_object->server . "/" . $flickr_object->primary . "_" . $flickr_object->secret . "_" . $short_code['thumb_size'] . ".jpg"));
890 $photonic_album->tile_image = esc_url($this->find_largest_image($flickr_object, $tile_size, $photonic_album->tile_size));
891
892 $owner = $flickr_object->owner ?? $short_code['user_id'];
893 $photonic_album->main_page = esc_url("https://www.flickr.com/photos/$owner/sets/{$flickr_object->id}");
894 $photonic_album->counter = $flickr_object->photos;
895
896 $internal_short_code['view'] = 'photoset';
897 $internal_short_code['photoset_id'] = $flickr_object->id;
898 }
899
900 $photonic_album->thumb_size = [
901 'w' => 's' === $short_code['thumb_size'] ? 75 : ('q' === $short_code['thumb_size'] ? 150 : $flickr_object->primary_photo_extras->{'width_' . $short_code['thumb_size']}),
902 'h' => 's' === $short_code['thumb_size'] ? 75 : ('q' === $short_code['thumb_size'] ? 150 : $flickr_object->primary_photo_extras->{'height_' . $short_code['thumb_size']}),
903 ];
904
905 if ('page' === $short_code['popup'] && !empty($photonic_gallery_template_page) && is_string(get_post_status($photonic_gallery_template_page))) {
906 $photonic_album->gallery_url = $this->get_gallery_url(
907 $internal_short_code,
908 [
909 'title' => $photonic_album->title,
910 ]
911 );
912 }
913
914 $objects[] = $photonic_album;
915 }
916 return $objects;
917 }
918
919 /**
920 * Prints the header for a photoset in a local, modal or template location.
921 *
922 * @param $photoset
923 * @param array $short_code
924 * @return Header
925 */
926 private function get_photoset_header($photoset, $short_code = []): Header {
927 global $photonic_flickr_hide_set_thumbnail, $photonic_flickr_hide_set_title, $photonic_flickr_hide_set_photo_count;
928
929 $owner = $photoset->owner;
930 $hidden = ['thumbnail' => !empty($photonic_flickr_hide_set_thumbnail), 'title' => !empty($photonic_flickr_hide_set_title), 'counter' => !empty($photonic_flickr_hide_set_photo_count)];
931
932 $header = new Header();
933 $header->title = wp_kses_post($photoset->title->_content);
934 $header->description = wp_kses_post($photoset->description->_content);
935 $header->thumb_url = esc_url($photoset->primary_photo_extras->{'url_' . $short_code['thumb_size']} ?? "https://farm{$photoset->farm}.staticflickr.com/{$photoset->server}/{$photoset->primary}_{$photoset->secret}_{$short_code['thumb_size']}.jpg");
936 $header->page_url = 'https://www.flickr.com/photos/' . $owner . '/sets/' . $photoset->id;
937
938 $header->header_for = 'set';
939 $header->hidden_elements = $this->get_hidden_headers($short_code['header_display'], $hidden);
940 $header->counters = ['photos' => $photoset->photos];
941 $header->enable_link = true;
942 $header->display_location = $short_code['display'];
943
944 return $header;
945 }
946
947 /**
948 * Prints thumbnails for each photoset returned in a query.
949 *
950 * @param $photosets
951 * @param array $filter_list
952 * @param array $short_code
953 * @return Album_List
954 */
955 private function get_photoset_list($photosets, array $filter_list = [], array $short_code = []): Album_List {
956 global $photonic_flickr_collection_set_per_row_constraint, $photonic_flickr_collection_set_constrain_by_count, $photonic_gallery_template_page,
957 $photonic_flickr_collection_set_title_display, $photonic_flickr_hide_collection_set_photos_count_display;
958 $options = ['type' => 'photoset'];
959 $objects = $this->build_level_2_objects($photosets->photoset, $short_code, $filter_list, $options);
960
961 $row_constraints = ['constraint-type' => $photonic_flickr_collection_set_per_row_constraint, 'count' => $photonic_flickr_collection_set_constrain_by_count];
962
963 $album_list = new Album_List($short_code);
964 $album_list->albums = $objects;
965 $album_list->row_constraints = $row_constraints;
966 $album_list->type = 'photosets';
967 $album_list->singular_type = 'set';
968 $album_list->title_position = $photonic_flickr_collection_set_title_display;
969 $album_list->level_1_count_display = $photonic_flickr_hide_collection_set_photos_count_display;
970 $album_list->pagination = $this->get_pagination($photosets);
971 $album_list->album_opens_gallery = ('page' === $short_code['popup'] && !empty($photonic_gallery_template_page) && is_string(get_post_status($photonic_gallery_template_page)));
972
973 return $album_list;
974 }
975
976 /**
977 * Shows the header for a gallery invoked in a local, template or modal.
978 *
979 * @param $gallery
980 * @param array $short_code
981 * @return Header
982 */
983 private function get_gallery_header($gallery, array $short_code): Header {
984 global $photonic_flickr_hide_gallery_thumbnail, $photonic_flickr_hide_gallery_title, $photonic_flickr_hide_gallery_photo_count;
985
986 $hidden = ['thumbnail' => !empty($photonic_flickr_hide_gallery_thumbnail), 'title' => !empty($photonic_flickr_hide_gallery_title), 'counter' => !empty($photonic_flickr_hide_gallery_photo_count)];
987
988 $header = new Header();
989 $header->title = wp_kses_post($gallery->title->_content);
990 $header->description = wp_kses_post($gallery->description->_content);
991 $header->thumb_url = esc_url($gallery->primary_photo_extras->{'url_' . $short_code['thumb_size']} ?? "https://farm{$gallery->primary_photo_farm}.staticflickr.com/{$gallery->primary_photo_server}/{$gallery->primary_photo_id}_{$gallery->primary_photo_secret}_{$short_code['thumb_size']}.jpg");
992 $header->page_url = $gallery->url;
993
994 $header->header_for = 'gallery';
995 $header->hidden_elements = $this->get_hidden_headers($short_code['header_display'], $hidden);
996 $header->counters = ['photos' => $gallery->count_photos];
997 $header->enable_link = true;
998 $header->display_location = $short_code['display'];
999
1000 return $header;
1001 }
1002
1003 /**
1004 * Prints out the thumbnails for all galleries belonging to a user.
1005 *
1006 * @param $galleries
1007 * @param array $filter_list
1008 * @param array $short_code
1009 * @return Album_List
1010 */
1011 private function get_gallery_list($galleries, $filter_list = [], $short_code = []): Album_List {
1012 global $photonic_flickr_galleries_per_row_constraint, $photonic_gallery_template_page,
1013 $photonic_flickr_galleries_constrain_by_count, $photonic_flickr_gallery_title_display, $photonic_flickr_hide_gallery_photos_count_display;
1014
1015 $options = ['type' => 'gallery'];
1016 $objects = $this->build_level_2_objects($galleries->gallery, $short_code, $filter_list, $options);
1017
1018 $row_constraints = ['constraint-type' => $photonic_flickr_galleries_per_row_constraint, 'count' => $photonic_flickr_galleries_constrain_by_count];
1019
1020 $album_list = new Album_List($short_code);
1021 $album_list->albums = $objects;
1022 $album_list->row_constraints = $row_constraints;
1023 $album_list->type = 'galleries';
1024 $album_list->singular_type = 'gallery';
1025 $album_list->title_position = $photonic_flickr_gallery_title_display;
1026 $album_list->level_1_count_display = $photonic_flickr_hide_gallery_photos_count_display;
1027 $album_list->pagination = $this->get_pagination($galleries);
1028 $album_list->album_opens_gallery = ('page' === $short_code['popup'] && !empty($photonic_gallery_template_page) && is_string(get_post_status($photonic_gallery_template_page)));
1029
1030 return $album_list;
1031 }
1032
1033 /**
1034 * Prints a collection header, followed by thumbnails of all sets in that collection.
1035 *
1036 * @param $collections
1037 * @param array $short_code
1038 * @return Collection
1039 */
1040 private function get_collections($collections, $short_code = []): Collection {
1041 global $photonic_flickr_hide_empty_collection_details, $photonic_flickr_collection_set_per_row_constraint, $photonic_gallery_template_page,
1042 $photonic_flickr_collection_set_constrain_by_count, $photonic_flickr_hide_collection_thumbnail, $photonic_flickr_hide_collection_title,
1043 $photonic_flickr_hide_collection_set_count, $photonic_flickr_collection_set_title_display, $photonic_flickr_hide_collection_set_photos_count_display;
1044 $photonic_collections = new Collection();
1045 if (!empty($short_code['strip_top_level'])) {
1046 $photonic_collections->strip_top_level = true;
1047 }
1048
1049 $row_constraints = ['constraint-type' => $photonic_flickr_collection_set_per_row_constraint, 'count' => $photonic_flickr_collection_set_constrain_by_count];
1050
1051 foreach ($collections->collection as $collection) {
1052 $photonic_collection = new Collection();
1053 if (!empty($short_code['strip_top_level'])) {
1054 $photonic_collection->strip_top_level = true;
1055 }
1056
1057 $dont_show = false;
1058 if (empty($collection->set) && !empty($photonic_flickr_hide_empty_collection_details)) {
1059 $dont_show = true;
1060 }
1061 $id = $collection->id;
1062 if (!$dont_show) {
1063 $url_id = substr($id, stripos($id, '-') + 1);
1064 if ('/images/collection_default_s.gif' === $collection->iconsmall) {
1065 $thumb = 'https://www.flickr.com' . $collection->iconsmall;
1066 }
1067 else {
1068 $thumb = $collection->iconsmall;
1069 }
1070
1071 $hidden = ['thumbnail' => !empty($photonic_flickr_hide_collection_thumbnail), 'title' => !empty($photonic_flickr_hide_collection_title), 'counter' => !empty($photonic_flickr_hide_collection_set_count)];
1072 $counters = [];
1073 if (isset($collection->set)) {
1074 $photosets = $collection->set;
1075 $counters['sets'] = count($photosets);
1076 }
1077
1078 $header = new Header();
1079 $header->id = $id . '-' . $short_code['user_id'];
1080 $header->title = wp_kses_post($collection->title);
1081 $header->description = wp_kses_post($collection->description ?? '');
1082 $header->thumb_url = $thumb;
1083 $header->page_url = "https://www.flickr.com/photos/{$short_code['user_id']}/collections/$url_id";
1084
1085 $header->header_for = 'collection';
1086 $header->hidden_elements = $this->get_hidden_headers($short_code['header_display'], $hidden);
1087 $header->counters = $counters;
1088 $header->enable_link = true;
1089 $header->iterate_level_3 = $short_code['iterate_level_3'];
1090 $header->layout = $short_code['layout'];
1091
1092 $photonic_collection->header = $header;
1093 }
1094
1095 if (isset($collection->set) && !empty($collection->set) && $short_code['iterate_level_3']) {
1096 $flickr_objects = [];
1097 $photosets = $collection->set;
1098
1099 $parallel = [];
1100 $psets = [];
1101 $hooks = new Hooks();
1102
1103 if (isset($hooks)) {
1104 $hooks->register('curl.before_multi_add', [$this, 'ssl_verify_peer'], 100);
1105 }
1106
1107 foreach ($photosets as $set) {
1108 $parallel_params = [];
1109 $parallel_params['primary_photo_extras'] = 'url_c,c_dims,url_h,h_dims,url_k,k_dims,url_o,o_dims,url_b,b_dims,url_z,z_dims,url_n,n_dims,url_m,m_dims,url_q,q_dims,url_t,t_dims,url_s,s_dims,media';
1110 $parallel_params['format'] = 'json';
1111 $parallel_params['nojsoncallback'] = 1;
1112 $parallel_params['api_key'] = $this->api_key;
1113 $parallel_params['method'] = 'flickr.photosets.getInfo';
1114 $parallel_params['photoset_id'] = $set->id;
1115 // We only worry about signing the call if the authentication is done. Otherwise we just show what is available.
1116 if ($this->oauth_done) {
1117 $signed_args = $this->sign_call($this->base_url, 'GET', $parallel_params);
1118 $parallel_params = $signed_args;
1119 }
1120
1121 $parallel[] = [
1122 'url' => $this->base_url,
1123 'type' => 'GET',
1124 'data' => $parallel_params,
1125 ];
1126 $psets[] = $set->id;
1127 }
1128
1129 if (!empty($parallel) && isset($hooks)) {
1130 $parallel_responses = Requests::request_multiple($parallel, ['hooks' => $hooks]); // DO NOT import this, since the class does not exist before WP 6.2
1131 if (!empty($parallel_responses)) {
1132 foreach ($parallel_responses as $ps_response) {
1133 if (is_a($ps_response, 'WpOrg\Requests\Response')) {
1134 $ps_response = json_decode($ps_response->body);
1135 if (!empty($ps_response->photoset->id)) {
1136 $flickr_objects[array_search($ps_response->photoset->id, $psets, true)] = $ps_response->photoset;
1137 }
1138 }
1139 }
1140 }
1141 }
1142 ksort($flickr_objects);
1143
1144 $options = ['type' => 'photoset'];
1145 $objects = $this->build_level_2_objects($flickr_objects, $short_code, [], $options); // No filters passed for this
1146
1147 $album_list = new Album_List($short_code);
1148 $album_list->albums = $objects;
1149 $album_list->row_constraints = $row_constraints;
1150 $album_list->type = 'photosets';
1151 $album_list->singular_type = 'set';
1152 $album_list->title_position = $photonic_flickr_collection_set_title_display;
1153 $album_list->level_1_count_display = $photonic_flickr_hide_collection_set_photos_count_display;
1154 $album_list->album_opens_gallery = ('page' === $short_code['popup'] && !empty($photonic_gallery_template_page) && is_string(get_post_status($photonic_gallery_template_page)));
1155
1156 $photonic_collection->album_list = $album_list;
1157 }
1158 $photonic_collections->collections[] = $photonic_collection;
1159 }
1160
1161 return $photonic_collections;
1162 }
1163
1164 /**
1165 * Access Token URL
1166 *
1167 * @return string
1168 */
1169 public function access_token_URL(): string {
1170 return 'https://www.flickr.com/services/oauth/access_token';
1171 }
1172
1173 /**
1174 * Authenticate URL
1175 *
1176 * @return string
1177 */
1178 public function authenticate_URL(): string {
1179 return 'https://www.flickr.com/services/oauth/authorize';
1180 }
1181
1182 /**
1183 * Authorize URL
1184 *
1185 * @return string
1186 */
1187 public function authorize_URL(): string {
1188 return 'https://www.flickr.com/services/oauth/authorize';
1189 }
1190
1191 /**
1192 * Request Token URL
1193 *
1194 * @return string
1195 */
1196 public function request_token_URL(): string {
1197 return 'https://www.flickr.com/services/oauth/request_token';
1198 }
1199
1200 /**
1201 * Method to validate that the stored token is indeed authenticated.
1202 *
1203 * @return array|WP_Error
1204 */
1205 public function check_access_token() {
1206 $parameters = ['method' => 'flickr.test.login', 'format' => 'json', 'nojsoncallback' => 1];
1207 $signed_parameters = $this->sign_call($this->base_url, 'GET', $parameters);
1208 $end_point = $this->base_url;
1209 $end_point .= '?' . self::build_query($signed_parameters);
1210 $parameters = null;
1211
1212 return Photonic::http($end_point, 'GET', $parameters, $this->user_agent);
1213 }
1214
1215 public function execute_helper($args = []): string {
1216 if (!empty($args['user'])) {
1217 $url = 'https://api.flickr.com/services/rest/?format=json&nojsoncallback=1&api_key=' . $this->api_key . '&method=flickr.urls.lookupUser&url=' . rawurlencode('https://www.flickr.com/photos/') . $args['user'];
1218 }
1219 elseif (!empty($args['group'])) {
1220 $url = 'https://api.flickr.com/services/rest/?format=json&nojsoncallback=1&api_key=' . $this->api_key . '&method=flickr.urls.lookupGroup&url=' . rawurlencode('https://www.flickr.com/groups/') . $args['group'];
1221 }
1222 else {
1223 return '<div class="photonic-helper">' . sprintf(esc_html__('Please pass the %1$s or %2$s attribute.', 'photonic'), '<code>user</code>', '<code>group</code>') . '</div>';
1224 }
1225
1226 $response = wp_remote_request($url, ['sslverify' => PHOTONIC_SSL_VERIFY]);
1227 if (!is_wp_error($response)) {
1228 if (isset($response['response']) && isset($response['response']['code'])) {
1229 if (200 === $response['response']['code']) {
1230 $body = json_decode(wp_remote_retrieve_body($response));
1231 if (isset($body->stat) && 'fail' === $body->stat) {
1232 Photonic::log($response);
1233 return '<div class="photonic-helper">' . wp_kses_post($body->message) . '</div>';
1234 }
1235
1236 if (isset($body->user)) {
1237 return '<div class="photonic-helper">' . sprintf(esc_html__('User id: %s', 'photonic'), esc_html($body->user->id)) . '</div>';
1238 }
1239 elseif (isset($body->group)) {
1240 return '<div class="photonic-helper">' . sprintf(esc_html__('Group id: %s', 'photonic'), esc_html($body->group->id)) . '</div>';
1241 }
1242 else {
1243 return '<div class="photonic-helper">' . esc_html__('No data returned.', 'photonic') . '</div>';
1244 }
1245 }
1246 else {
1247 Photonic::log($response['response']);
1248 return '<div class="photonic-helper">' . sprintf(esc_html__('No data returned. Error code %s', 'photonic'), esc_html($response['response']['code'])) . '</div>';
1249 }
1250 }
1251 else {
1252 Photonic::log($response);
1253 return '<div class="photonic-helper">' . esc_html__('No data returned. Empty response, or empty error code.', 'photonic') . '</div>';
1254 }
1255 }
1256 else {
1257 return '<div class="photonic-helper">' . wp_kses_post($response->get_error_message()) . '</div>';
1258 }
1259 }
1260
1261 /**
1262 * @param $entity
1263 * @param array $short_code
1264 * @return Pagination
1265 */
1266 public function get_pagination($entity, array $short_code = []): Pagination {
1267 $per_page = $entity->perpage ?? $entity->per_page;
1268
1269 $pagination = new Pagination();
1270 $pagination->total = $entity->total;
1271 $pagination->start = ($entity->page - 1) * $per_page + 1;
1272 $pagination->end = min($entity->page * $per_page, $entity->total);
1273 $pagination->per_page = $per_page;
1274
1275 return $pagination;
1276 }
1277 }
1278