PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 2.34
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v2.34
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 / extensions / Photonic_Flickr_Processor.php

Photonic_Flickr_Processor.php in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 2.34, at extensions/Photonic_Flickr_Processor.php

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