PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 3.36
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v3.36
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.36, at Platforms/Flickr.php

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