PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 2.40
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v2.40
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 / Modules / SmugMug.php

SmugMug.php in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 2.40, at Modules/SmugMug.php

968 lines 32.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Photonic_Plugin\Modules;
3
4 use Photonic_Plugin\Core\Photonic;
5 use WP_Error;
6
7 require_once('OAuth1.php');
8 require_once('Level_One_Module.php');
9
10 class SmugMug extends OAuth1 implements Level_One_Module {
11 var $highlights_processed;
12 private static $instance = null;
13
14 protected function __construct() {
15 parent::__construct();
16 global $photonic_smug_api_key, $photonic_smug_api_secret, $photonic_smug_access_token, $photonic_smug_disable_title_link, $photonic_smug_token_secret, $photonic_smug_show_buy_link;
17 // $this->api_key = trim($photonic_smug_api_key);
18 $this->api_key = !empty($photonic_smug_api_key) ? trim($photonic_smug_api_key) : '86MZ8N8TqJf5x2fQ4FRWXRtJ3C6Jm7XV';
19 $this->api_secret = trim($photonic_smug_api_secret);
20 $this->token = trim($photonic_smug_access_token);
21 $this->token_secret = trim($photonic_smug_token_secret);
22 $this->provider = 'smug';
23 $this->link_lightbox_title = empty($photonic_smug_disable_title_link);
24 $this->oauth_version = '1.0a';
25 $this->base_url = 'https://api.smugmug.com/api/v2/';
26 $this->show_buy_link = !empty($photonic_smug_show_buy_link);
27
28 $this->doc_links = [
29 'general' => 'https://aquoid.com/plugins/photonic/smugmug/',
30 'photos' => 'https://aquoid.com/plugins/photonic/smugmug/smugmug-photos/',
31 'albums' => 'https://aquoid.com/plugins/photonic/smugmug/smugmug-albums/',
32 'tree' => 'https://aquoid.com/plugins/photonic/smugmug/smugmug-tree/',
33 'folders' => 'https://aquoid.com/plugins/photonic/smugmug/folders/',
34 ];
35
36 $this->set_oauth_done();
37 $this->highlights_processed = [];
38 }
39
40 public static function get_instance() {
41 if (self::$instance == null) {
42 self::$instance = new SmugMug();
43 }
44 return self::$instance;
45 }
46
47 /**
48 * The main gallery builder for SmugMug. SmugMug takes the following parameters:
49 * - nick_name = The nickname of the user. This is mandatory for SmugMug.
50 * - view = tree | albums | album | images. If left blank, a value of 'tree' is assumed.
51 * - columns = The number of columns to show the output in
52 * - album or album_key = The album slug, which is the AlbumKey. This is needed if view='album' or 'images'. Prior to version 1.57 album_id was required
53 * - empty = true | false. If true, empty albums and categories are returned in the response, otherwise they are ignored.
54 * - columns = The number of columns to return the output in. Optional.
55 *
56 * @param array $attr
57 * @param array $gallery_meta
58 * @return string
59 */
60 public function get_gallery_images($attr = [], &$gallery_meta = []) {
61 global $photonic_smug_title_caption, $photonic_smug_album_sort_order;
62 global $photonic_smug_thumb_size, $photonic_smug_main_size, $photonic_smug_tile_size, $photonic_smug_video_size, $photonic_smug_media, $photonic_smug_default_user;
63 $this->gallery_index++;
64 $this->push_to_stack('Get Gallery Images');
65
66 if (empty($this->api_key)) {
67 $this->pop_from_stack();
68 return $this->error(esc_html__('SmugMug API Key not defined.', 'photonic').Photonic::doc_link($this->doc_links['general']));
69 }
70
71 $attr = array_merge(
72 $this->common_parameters,
73 [
74 'caption' => $photonic_smug_title_caption,
75 'thumb_size' => $photonic_smug_thumb_size,
76 'main_size' => $photonic_smug_main_size,
77 'tile_size' => $photonic_smug_tile_size,
78 'video_size' => $photonic_smug_video_size,
79
80 'empty' => 'false',
81 'view' => 'tree',
82 'nick_name' => $photonic_smug_default_user,
83 'start' => 1,
84 'count' => 500,
85 'media' => $photonic_smug_media,
86 'album_sort_order' => $photonic_smug_album_sort_order,
87 ],
88 $attr);
89
90 /* if ($attr['main_size'] == 'custom') {
91 if (!empty($attr['custom_main_size'])) {
92 $attr['main_size'] = $attr['custom_main_size'];
93 }
94 else {
95 $attr['main_size'] = 'Largest';
96 }
97 }
98 if ($attr['thumb_size'] == 'custom') {
99 if (!empty($attr['custom_thumb_size'])) {
100 $attr['thumb_size'] = $attr['custom_thumb_size'];
101 }
102 else {
103 $attr['thumb_size'] = 'Tiny';
104 }
105 }
106 if ($attr['tile_size'] == 'custom' && !empty($attr['custom_tile_size'])) {
107 if (!empty($attr['custom_tile_size'])) {
108 $attr['tile_size'] = $attr['custom_tile_size'];
109 }
110 else {
111 $attr['tile_size'] = 'same';
112 }
113 }*/
114
115 $attr = array_map('trim', $attr);
116 extract($attr);
117
118 $args = [
119 'APIKey' => $this->api_key,
120 '_accept' => 'application/json'
121 ];
122
123 $chained_calls = [];
124
125 $args['_expandmethod'] = 'inline';
126 $args['_verbosity'] = '1';
127
128 if ($attr['view'] == 'tree' || $attr['view'] == 'albums') {
129 if (empty($attr['nick_name'])) {
130 $this->pop_from_stack();
131 return $this->error(sprintf(esc_html__('The %1$s attribute is required for the %2$s and %3$s views.', 'photonic'), '<code>nick_name</code>', '<code>tree</code>', '<code>albums</code>'));
132 }
133 }
134
135 switch ($attr['view']) {
136 case 'albums':
137 if (!empty($attr['site_password'])) {
138 $chained_calls[] = $this->base_url.'user/'.$attr['nick_name'].'!unlock';
139 $args['Password'] = $attr['site_password'];
140 }
141
142 $chained_calls[] = $this->base_url.'user/'.$attr['nick_name'].'!albums';
143 $args['_expand'] = 'HighlightImage.ImageSizes';
144 $args['Order'] = $attr['album_sort_order'];
145
146 break;
147
148 case 'album':
149 case 'images':
150 $album_field = '';
151 $is_album = true;
152 if (!empty($attr['album_key'])) {
153 $album_field = $attr['album_key'];
154 }
155 else if (!empty($attr['album'])) {
156 if (stripos($attr['album'], '_') === FALSE) {
157 $album_field = $attr['album'];
158 }
159 else {
160 $album_field = substr($attr['album'], stripos($attr['album'], '_') + 1);
161 }
162 }
163 else {
164 $is_album = false;
165 }
166
167 if (!empty($attr['password']) || !empty($attr['site_password'])) {
168 $args['Password'] = !empty($attr['password']) ? $attr['password'] : $attr['site_password'];
169 $chained_calls[] = $this->base_url.'album/'.$album_field.'!unlock';
170 }
171
172 if (!empty($attr['text'])) {
173 $args['Text'] = $attr['text'];
174 }
175 if (!empty($attr['keywords'])) {
176 $keywords = explode(',', $attr['keywords']);
177 $keywords = json_encode($keywords);
178 $args['Keywords'] = $keywords;
179 }
180 if (!empty($attr['sort_method'])) {
181 $args['SortMethod'] = $attr['sort_method'];
182 }
183 if (!empty($attr['sort_order'])) {
184 $args['SortDirection'] = $attr['sort_order'];
185 }
186
187 /*
188 Weird issue: If _expand is called with a comma-separated list, and is passed in $args[], it doesn't expand everything.
189 So, for comma-separated values, _expand is appended to the URL.
190 However, if we do this, and OAuth is being used, the signature generation gets messed up, as the signature is generated with the "?_expand=...",
191 which doesn't match the signature for when we make a call with $signed_args, because SmugMug internally parses out the URL and puts _expand=...
192 somewhere in the middle. So, to fix, for authenticated calls we are separating out the _expand parameter and making two calls. Additionally we are
193 moving the parameter from the URL to the array in the generate_signature method.
194
195 Update, v1.59 - Using _expand and combining both the expansions prevents the usage of the <code>start</code> and <code>count</code>
196 attributes from the album node. So, splitting the call anyway, to introduce the album!images node...
197 */
198 if ($is_album) {
199 $chained_calls[] = $this->base_url.'album/'.$album_field.'?_expand=HighlightImage.ImageSizes';
200 if ($attr['view'] == 'images') {
201 $args['Scope'] = 'https://api.smugmug.com/api/v2/album/'.$album_field;
202 }
203 else {
204 $chained_calls[] = $this->base_url.'album/'.$album_field.'!images?_expand=ImageSizes';
205 }
206 }
207 else if (!empty($attr['nick_name']) || !empty($attr['folder'])) {
208 if (!empty($attr['folder'])) {
209 $args['Scope'] = 'https://api.smugmug.com/api/v2/node/'.$attr['folder'];
210 }
211 else {
212 $args['Scope'] = 'https://api.smugmug.com/api/v2/user/'.$attr['nick_name'];
213 }
214 }
215
216 if (!empty($args['Scope'])) {
217 // Only search if you have view='images'
218 $chained_calls[] = 'https://api.smugmug.com/api/v2/image!search?_expand=ImageSizes';
219 }
220
221 break;
222
223 case 'folder':
224 if (!empty($attr['folder'])) {
225 $this->prepare_chained_calls_for_folder($chained_calls, $attr['folder'], $attr['count']);
226 }
227 break;
228
229 case 'tree':
230 default:
231 $this->push_to_stack('Initial user tree');
232 $initial_call = $this->base_url.'user/'.$attr['nick_name'];
233 $initial_response = Photonic::http($initial_call, 'GET', $args);
234
235 if (!empty($attr['site_password'])) {
236 $chained_calls[] = $this->base_url.'user/'.$attr['nick_name'].'!unlock';
237 $args['Password'] = $attr['site_password'];
238 }
239
240 if (is_array($initial_response['response']) && isset($initial_response['response']['code']) && $initial_response['response']['code'] === 200) {
241 $body = $initial_response['body'];
242 $body = json_decode($body);
243 $body = $body->Response;
244 $node = $body->User->Uris->Node->Uri;
245 $pieces = explode('/', $node);
246 $node = array_pop($pieces);
247 $this->prepare_chained_calls_for_folder($chained_calls, $node, $attr['count']);
248 }
249 $this->pop_from_stack();
250 break;
251 }
252
253 if (!empty($attr['nick_name'])) {
254 $args['NickName'] = $attr['nick_name'];
255 }
256
257 if (!empty($attr['start'])) {
258 $args['start'] = $attr['start'];
259 }
260
261 if (!empty($attr['count'])) {
262 $args['count'] = $attr['count'];
263 }
264 $attr['photo_count'] = empty($attr['photo_count']) ? $attr['count'] : $attr['photo_count'];
265
266 $attr['overlay_size'] = empty($attr['overlay_size']) ? $attr['thumb_size'] : $attr['overlay_size'];
267 $attr['overlay_video_size'] = empty($attr['overlay_video_size']) ? $attr['video_size'] : $attr['overlay_video_size'];
268
269 $ret = '';
270 $header_display = $this->get_header_display($attr);
271 $attr['header_display'] = $header_display;
272
273 $ret .= $this->make_chained_calls($chained_calls, $args, $attr, $gallery_meta);
274 $this->pop_from_stack();
275 return $ret.$this->get_stack_markup();
276 }
277
278 /**
279 * Runs a sequence of web-service calls to get information. Most often a single web-service call with the "Extras" parameter suffices for SmugMug.
280 * But there are some scenarios, e.g. clicking on an album to get a popup of all images in that album, where you need to chain the calls for the header.
281 *
282 * @param $chained_calls
283 * @param $smug_args
284 * @param $short_code
285 * @param array $gallery_meta
286 * @return string
287 */
288 function make_chained_calls($chained_calls, $smug_args, $short_code, &$gallery_meta = []) {
289 $this->push_to_stack('Make chained calls');
290 $header_done = false;
291
292 if (is_array($chained_calls) && count($chained_calls) > 0) {
293 extract($short_code);
294
295 $ret = '';
296
297 $cookies = [];
298 $insert = '';
299
300 foreach ($chained_calls as $chained_call) {
301 $this->push_to_stack("Chained call: $chained_call");
302 if (stripos($chained_call, '!unlock') !== FALSE) {
303 $response = Photonic::http($chained_call, 'POST', $smug_args);
304 if (!is_wp_error($response)) {
305 if (is_array($response['response']) && isset($response['response']['code']) && $response['response']['code'] === 200) {
306 $cookies = $response['cookies'];
307 foreach ($response['cookies'] as $cookie) {
308 $cookies[$cookie->name] = $cookie->value;
309 }
310 }
311 }
312 else {
313 $this->pop_from_stack(); // 'Chained call'
314 $this->pop_from_stack(); // 'Make chained calls'
315 return $this->wp_error_message($response);
316 }
317 }
318
319 // The following is NOT an "else" because we are modifying the headers with the cookies, if required
320 if (stripos($chained_call, '!unlock') === FALSE) {
321 $this->push_to_stack('Making call');
322 if ($this->oauth_done && empty($cookies)) {
323 $signed_args = $this->sign_call($chained_call, 'GET', $smug_args);
324 $response = Photonic::http($chained_call, 'GET', $signed_args, null, 90, false, [], $cookies);
325 }
326 else {
327 $response = Photonic::http($chained_call, 'GET', $smug_args, null, 90, false, [], $cookies);
328 }
329
330 $this->pop_from_stack();
331
332 if (!is_wp_error($response)) {
333 $body = $response['body'];
334 $body = json_decode($body);
335
336 if ($body->Code === 200) {
337 $body = $body->Response;
338 if (stripos($chained_call, '!albums') !== FALSE) {
339 $albums = $body->Album;
340 if (is_array($albums) && count($albums) > 0) {
341 $filter = [];
342 if (!empty($short_code['filter'])) {
343 $filter = explode(',', $short_code['filter']);
344 }
345 $album_text = $this->process_albums($albums, '', $filter, $short_code, $body->Pages);
346 if (!empty($album_text)) {
347 $ret .= $this->finalize_markup($album_text, $short_code);
348 }
349 }
350 }
351 else if ((stripos($chained_call, '/album/') !== FALSE || (stripos($chained_call, '/image!search') !== FALSE && stripos($chained_call, urlencode('/api/v2/album/')) !== FALSE)) && stripos($chained_call, '!unlock') === FALSE) {
352 $password_check_passed = true;
353 if (isset($body->Album)) {
354 $album = $body->Album;
355 $password_check_passed = ($album->SecurityType == 'Password' && isset($album->Uris->AlbumImages)) || $album->SecurityType != 'Password';
356
357 $header_object = [];
358 $header_object['title'] = $album->Name;
359 $header_object['link_url'] = $album->WebUri;
360 $header_object['description'] = $album->Description;
361
362 if (isset($album->Uris->HighlightImage->Image)) {
363 $header_object['thumb_url'] = $album->Uris->HighlightImage->Image->ThumbnailUrl;
364 }
365 else if (isset($album->Uris->AlbumImages->AlbumImage) && is_array($album->Uris->AlbumImages->AlbumImage)) {
366 $rand = rand(0, $album->ImageCount - 1);
367 $header_object['thumb_url'] = $album->Uris->AlbumImages->AlbumImage[$rand]->ThumbnailUrl;
368 }
369
370 global $photonic_smug_disable_title_link, $photonic_smug_hide_album_thumbnail, $photonic_smug_hide_album_title, $photonic_smug_hide_album_photo_count;
371 $hidden = [
372 'thumbnail' => !empty($photonic_smug_hide_album_thumbnail),
373 'title' => !empty($photonic_smug_hide_album_title),
374 'counter' => !empty($photonic_smug_hide_album_photo_count),
375 ];
376 $counters = ['photos' => !isset($album->ImageCount) ? 0 : $album->ImageCount];
377
378 if (empty($display)) {
379 $display = 'in-page';
380 }
381
382 if (!$header_done) {
383 $insert = $this->process_object_header($header_object,
384 [
385 'type' => 'album',
386 'hidden' => $this->get_hidden_headers($short_code['header_display'], $hidden),
387 'counters' => $counters,
388 'link' => empty($photonic_smug_disable_title_link),
389 'display' => $display,
390 ],
391 $gallery_meta
392 );
393 $header_done = true;
394 }
395 }
396 if ($password_check_passed) {
397 $ret .= $this->process_images($response, $short_code, $insert);
398 }
399 else {
400 $ret .= $this->password_protected;
401 }
402 }
403 else if (stripos($chained_call, '/user/') !== FALSE) {
404 $root_node = $body->User->Uris->Node->Node;
405 $ret .= $this->process_node($root_node, $short_code);
406 }
407 else if (stripos($chained_call, '/node/') !== FALSE) {
408 $ret .= $this->process_node($body->Node, $short_code);
409 }
410 else if (stripos($chained_call, '/image!search') !== FALSE) {
411 $ret .= $this->process_images($response, $short_code, $insert);
412 }
413 }
414 }
415 else {
416 $this->pop_from_stack(); // 'Chained call'
417 $this->pop_from_stack(); // 'Make chained calls'
418 return $this->wp_error_message($response);
419 }
420 }
421 $this->pop_from_stack();
422 }
423 $this->pop_from_stack();
424 return $ret;
425 }
426 $this->pop_from_stack();
427 return '';
428 }
429
430 function get_config_object($count = 500) {
431 $config = [
432 'expand' => [
433 'HighlightImage' => [
434 'expand' => [
435 'ImageSizes' => []
436 ],
437 ],
438 'NodeCoverImage' => [
439 'expand' => [
440 'ImageSizes' => []
441 ],
442 ],
443 'ChildNodes' => [
444 'args' => [
445 'count' => $count
446 ],
447 'expand' => [
448 'HighlightImage' => [
449 'expand' => [
450 'ImageSizes' => []
451 ],
452 ],
453 'NodeCoverImage' => [
454 'expand' => [
455 'ImageSizes' => []
456 ],
457 ],
458 'ChildNodes' => [
459 'args' => [
460 'count' => $count
461 ],
462 'expand' => [
463 'HighlightImage' => [
464 'expand' => [
465 'ImageSizes' => []
466 ],
467 ],
468 'NodeCoverImage' => [
469 'expand' => [
470 'ImageSizes' => []
471 ],
472 ],
473 'ChildNodes' => [
474 'args' => [
475 'count' => $count
476 ],
477 'expand' => [
478 'HighlightImage' => [
479 'expand' => [
480 'ImageSizes' => []
481 ],
482 ],
483 'NodeCoverImage' => [
484 'expand' => [
485 'ImageSizes' => []
486 ],
487 ],
488 'ChildNodes' => [
489 'args' => [
490 'count' => $count
491 ],
492 'expand' => [
493 'HighlightImage' => [
494 'expand' => [
495 'ImageSizes' => []
496 ],
497 ],
498 'NodeCoverImage' => [
499 'expand' => [
500 'ImageSizes' => []
501 ],
502 ],
503 'ChildNodes' => [
504 'args' => [
505 'count' => $count
506 ],
507 ],
508 ],
509 ],
510 ],
511 ],
512 ],
513 ],
514 ],
515 ],
516 ],
517 ];
518 return $config;
519 }
520
521 function prepare_chained_calls_for_folder(&$chained_calls, $folder_node, $count) {
522 $config = $this->get_config_object($count);
523 $config_str = json_encode($config);
524
525 if (!empty($folder_node)) {
526 $chained_calls[] = $this->base_url.'node/'.$folder_node.'?_config='.$config_str;
527 }
528 }
529
530 function process_node($node, $short_code, $indent = '', $level = 0) {
531 $start = $indent."<ul class='photonic-tree'>\n";
532 $ret = $start;
533
534 $albums = [];
535 $folders = [];
536
537 if (is_array($node)) {
538 foreach($node as $child) {
539 if ($child->Type == 'Album') {
540 if (!in_array($child->NodeID.'-'.$this->gallery_index, $this->highlights_processed)) {
541 $this->highlights_processed[] = $child->NodeID.'-'.$this->gallery_index;
542 $albums[] = $child;
543 }
544 }
545 else if ($child->Type == 'Folder') {
546 $folders[] = $child;
547 }
548 }
549 }
550 else if ($node->Type == 'Folder') {
551 if (isset($node->Uris->ChildNodes->Node)) {
552 $child_nodes = $node->Uris->ChildNodes->Node;
553 foreach ($child_nodes as $child) {
554 if ($child->Type == 'Album'){
555 if (!in_array($child->NodeID.'-'.$this->gallery_index, $this->highlights_processed)) {
556 $this->highlights_processed[] = $child->NodeID.'-'.$this->gallery_index;
557 }
558 else {
559 continue;
560 }
561
562 if (isset($child->Uris->Album->Album)) {
563 $albums[] = $child->Uris->Album->Album; // Tree?
564 }
565 else {
566 $albums[] = $child; // Node?
567 }
568 }
569 else if ($child->Type == 'Folder') {
570 $folders[] = $child;
571 }
572 }
573 }
574 }
575
576 if (count($albums) > 0 || count($folders) > 0) {
577 if (!is_array($node)) {
578 $header_object = [
579 'title' => $node->Name,
580 ];
581 $hidden = ['thumbnail' => true, 'title' => false, 'counter' => false,];
582 $insert = $this->process_object_header($header_object,
583 [
584 'type' => 'folder',
585 'hidden' => $this->get_hidden_headers($short_code['header_display'], $hidden),
586 'counters' => [],
587 'link' => false,
588 'display' => 'in-page',
589 ]
590 );
591 }
592 }
593
594 if (count($albums) > 0) {
595 $album_text = $this->process_albums($albums, $indent . "\t\t", [], $short_code, null);
596 if (!empty($album_text)) {
597 $ret .= $indent."\t<li>\n";
598 $ret .= empty($insert) ? '' : $insert;
599 $ret .= $album_text;
600 $ret .= $indent."\t</li>\n";
601 }
602 }
603
604 if (count($folders) > 0) {
605 $folder_tree = '';
606 foreach ($folders as $folder) {
607 $folder_tree .= $this->process_node($folder, $short_code, $indent."\t\t", $level + 1);
608 }
609 if (!empty($folder_tree)) {
610 $ret .= $indent."\t<li>\n";
611 $ret .= empty($insert) ? '' : $insert;
612 $ret .= $folder_tree;
613 $ret .= $indent."\t</li>\n";
614 }
615 }
616
617 if ($ret != $start) {
618 $ret .= $indent."</ul>\n";
619 }
620 else {
621 // Nothing was found ...
622 $ret = "";
623 }
624 return $ret;
625 }
626
627 /**
628 * Parse an array of album objects returned by the SmugMug API, then return an appropriate response.
629 *
630 * @param $albums
631 * @param string $indent
632 * @param array $album_filter
633 * @param $short_code
634 * @param $pages
635 * @return string
636 */
637 function process_albums($albums, $indent, $album_filter, $short_code, $pages) {
638 global $photonic_smug_albums_album_per_row_constraint, $photonic_smug_albums_album_constrain_by_count, $photonic_smug_albums_album_constrain_by_padding, $photonic_smug_albums_album_title_display, $photonic_smug_hide_albums_album_photos_count_display;
639 $objects = $this->build_level_2_objects($albums, $short_code, $album_filter);
640 $pagination = [];
641 if (!empty($pages)) {
642 $pagination['total'] = $pages->Total;
643 $pagination['start'] = $pages->Start;
644 $pagination['end'] = $pages->Start + $pages->Count - 1;
645 $pagination['per-page'] = $pages->RequestedCount;
646 $pagination['provider'] = 'smug';
647 }
648
649 $row_constraints = ['constraint-type' => $photonic_smug_albums_album_per_row_constraint, 'padding' => $photonic_smug_albums_album_constrain_by_padding, 'count' => $photonic_smug_albums_album_constrain_by_count];
650 $ret = $this->layout_gallery($objects,
651 [
652 'row_constraints' => $row_constraints,
653 'type' => 'albums',
654 'singular_type' => 'album',
655 'title_position' => $photonic_smug_albums_album_title_display,
656 'level_1_count_display' => $photonic_smug_hide_albums_album_photos_count_display,
657 'pagination' => $pagination,
658 'indent' => $indent,
659 ],
660 $short_code,
661 2
662 );
663 return $ret;
664 }
665
666 /**
667 * Takes a response, then parses out the images from that response and returns a set of thumbnails for it. This method handles
668 * both, in-page images as well as images in a popup panel.
669 *
670 * @param $response
671 * @param array $short_code
672 * @param null $header
673 * @return string
674 */
675 function process_images($response, $short_code, $header) {
676 global $photonic_smug_photos_per_row_constraint, $photonic_smug_photos_constrain_by_count, $photonic_smug_photos_constrain_by_padding,
677 $photonic_smug_photos_pop_per_row_constraint, $photonic_smug_photos_pop_constrain_by_count,
678 $photonic_smug_photos_pop_constrain_by_padding, $photonic_smug_photo_title_display, $photonic_smug_photo_pop_title_display;
679 $body = $response['body'];
680 $body = json_decode($body);
681
682 if ($body->Message == 'Ok') {
683 $body = $body->Response;
684 if (isset($body->Album)) {
685 $album = $body->Album;
686 $images = $album->Uris->AlbumImages;
687 }
688 else if (isset($body->Image)) {
689 $images = $body->Image;
690 }
691 else {
692 $images = $body;
693 }
694
695 $photo_objects = [];
696 if (isset($images->AlbumImage)) {
697 $photo_objects = $this->build_level_1_objects($images->AlbumImage, $short_code);
698 }
699 if (is_array($images)) {
700 $photo_objects = $this->build_level_1_objects($images, $short_code);
701 }
702 $level_2_meta = [];
703 $pages = isset($images->Pages) ? $images->Pages : (is_array($images) && isset($body->Pages) ? $body->Pages : null);
704 if (isset($pages)) {
705 $level_2_meta['total'] = $pages->Total;
706 $level_2_meta['start'] = $pages->Start;
707 $level_2_meta['end'] = $pages->Start + $pages->Count - 1;
708 $level_2_meta['per-page'] = $pages->RequestedCount;
709 $level_2_meta['provider'] = 'smug';
710 }
711
712 $ret = "";
713 if (!empty($photo_objects)) {
714 if (isset($short_code['display']) && $short_code['display'] == 'popup') {
715 $ret .= $header;
716
717 $row_constraints = ['constraint-type' => $photonic_smug_photos_pop_per_row_constraint, 'padding' => $photonic_smug_photos_pop_constrain_by_padding, 'count' => $photonic_smug_photos_pop_constrain_by_count];
718 $ret .= $this->layout_gallery($photo_objects,
719 [
720 'title_position' => $photonic_smug_photo_pop_title_display,
721 'row_constraints' => $row_constraints,
722 'parent' => 'album',
723 'level_2_meta' => $level_2_meta,
724 ],
725 $short_code,
726 1
727 );
728 }
729 else {
730 $ret .= $header;
731
732 $row_constraints = ['constraint-type' => $photonic_smug_photos_per_row_constraint, 'padding' => $photonic_smug_photos_constrain_by_padding, 'count' => $photonic_smug_photos_constrain_by_count];
733 $ret .= $this->layout_gallery($photo_objects,
734 [
735 'title_position' => $photonic_smug_photo_title_display,
736 'row_constraints' => $row_constraints,
737 'parent' => 'album',
738 'level_2_meta' => $level_2_meta,
739 ],
740 $short_code,
741 1
742 );
743 }
744 return $this->finalize_markup($ret, $short_code);
745 }
746 }
747 return '';
748 }
749
750 function construct_custom_size($custom, $sizes) {
751 if (isset($sizes->LargeImageUrl)) {
752 $custom = str_replace('ImageUrl', '', $custom);
753 $large = $sizes->LargeImageUrl;
754 $split = explode('/', $large);
755 $split[count($split) - 2] = $custom;
756 $image_parts = explode('.', $split[count($split) -1]);
757 $image_name_parts = explode('-', $image_parts[count($image_parts) - 2]);
758 $image_name_parts[count($image_name_parts) - 1] = $custom;
759 $image_parts[count($image_parts) - 2] = implode('-', $image_name_parts);
760 $split[count($split) - 1] = implode('.', $image_parts);
761 return implode('/', $split);
762 }
763 return '';
764 }
765
766 function build_level_1_objects($images, $short_code, $module_parameters = [], $options = []) {
767 $thumb = "{$short_code['thumb_size']}ImageUrl";
768 $main = "{$short_code['main_size']}ImageUrl";
769 $tile = (empty($short_code['tile_size']) || $short_code['tile_size'] == 'same') ? $main : "{$short_code['tile_size']}ImageUrl";
770
771 $media = explode(',', $short_code['media']);
772 $videos_ok = in_array('videos', $media) || in_array('all', $media);
773 $photos_ok = in_array('photos', $media) || in_array('all', $media);
774
775 $photo_objects = [];
776 if (is_array($images) && count($images) > 0) {
777 foreach ($images as $image) {
778 if ((empty($image->IsVideo) && !$photos_ok) || (!empty($image->IsVideo) && !$videos_ok)) {
779 continue;
780 }
781 $image_sizes = $image->Uris->ImageSizes->ImageSizes;
782
783 $photo_object = [];
784 $photo_object['thumbnail'] = isset($image_sizes->{$thumb}) ? $image_sizes->{$thumb} : $this->construct_custom_size($thumb, $image_sizes);
785 $photo_object['main_image'] = isset($image_sizes->{$main}) ? $image_sizes->{$main} : $this->construct_custom_size($main, $image_sizes);//$image_sizes->{$main};
786 $photo_object['tile_image'] = isset($image_sizes->{$tile}) ? $image_sizes->{$tile} : $this->construct_custom_size($tile, $image_sizes);//$image_sizes->{$tile};
787 $photo_object['title'] = $image->Title;
788 $photo_object['alt_title'] = $image->Title;
789 $photo_object['description'] = $image->Caption;
790 if (isset($image->WebUri)) {
791 $photo_object['main_page'] = $image->WebUri;
792 $photo_object['buy_link'] = $image->WebUri.'/buy';
793 }
794
795 if (!empty($image->IsVideo)) {
796 $photo_object['video'] = $image_sizes->{$short_code['video_size'].'VideoUrl'};
797 }
798
799 if (isset($image->ArchivedUri)) {
800 $photo_object['download'] = $image->ArchivedUri;
801 }
802 $photo_object['id'] = $image->ImageKey;
803
804 $photo_object['provider'] = $this->provider;
805
806 $photo_objects[] = $photo_object;
807 }
808 }
809 return $photo_objects;
810 }
811
812 function build_level_2_objects($albums, $short_code, $album_filter = []) {
813 global $photonic_smug_hide_password_protected_thumbnail, $photonic_gallery_template_page;
814
815 $named_albums = $album_filter;
816 foreach ($named_albums as $idx => $album) {
817 if (stripos($album, '_') !== FALSE) {
818 $named_albums[$idx] = substr($album, stripos($album, '_') + 1);
819 }
820 }
821
822 $objects = [];
823 if (is_array($albums) && count($albums) > 0) {
824 foreach ($albums as $album) {
825 if (!empty($photonic_smug_hide_password_protected_thumbnail) && isset($album->SecurityType) && $album->SecurityType != 'None') {
826 continue;
827 }
828
829 $main = "{$short_code['main_size']}ImageUrl";
830 $tile = (empty($short_code['tile_size']) || $short_code['tile_size'] == 'same') ? $main : "{$short_code['tile_size']}ImageUrl";
831
832 $highlight = $album->Uris->HighlightImage;
833 if ((!isset($album->ImageCount) || $album->ImageCount != 0) /*&& isset($highlight->Image)*/) {
834 if (isset($highlight->Image)) {
835 $thumbURL = $highlight->Image->Uris->ImageSizes->ImageSizes->{$short_code['thumb_size'].'ImageUrl'};
836 $tileURL = $highlight->Image->Uris->ImageSizes->ImageSizes->$tile;
837 }
838 else {
839 if (in_array($short_code['thumb_size'], ['Small', 'Thumb', 'Tiny', 'Sm', 'Th', 'Ti'])) {
840 $thumbURL = trailingslashit(PHOTONIC_URL).'include/images/placeholder-'.substr($short_code['thumb_size'],0,2).'.png';
841 }
842 else {
843 $thumbURL = trailingslashit(PHOTONIC_URL).'include/images/placeholder.png';
844 }
845 $tileURL = trailingslashit(PHOTONIC_URL).'include/images/placeholder.png';
846 }
847
848 $object = [];
849 if (isset($album->AlbumKey)) {
850 $object['id_1'] = $album->AlbumKey;
851 }
852 else {
853 $uri = $album->Uris->Album->Uri;
854 $uri = explode('/', $uri);
855 $object['id_1'] = $uri[count($uri)-1];
856 }
857 $object['thumbnail'] = $thumbURL;
858 $object['tile_image'] = $tileURL;
859 $object['main_page'] = $album->WebUri;
860
861 $object['title'] = esc_attr($album->Name);
862 $object['description'] = !empty($album->Description) ? esc_attr($album->Description) : '';
863
864 if ($short_code['popup'] == 'page' && !empty($photonic_gallery_template_page) && is_string(get_post_status($photonic_gallery_template_page))) {
865 $internal_short_code = $short_code;
866 $internal_short_code['view'] = 'album';
867 $internal_short_code['album'] = $object['id_1'];
868 $internal_short_code['layout'] = empty($short_code['photo_layout']) ? $short_code['layout'] : $short_code['photo_layout'];
869
870 $object['gallery_url'] = $this->get_gallery_url($internal_short_code, ['title' => $object['title']]);
871 }
872
873 if (isset($album->ImageCount)) {
874 $object['counter'] = $album->ImageCount;
875 }
876
877 $object['data_attributes'] = [
878 'photo-count' => $short_code['photo_count'],
879 'photo-more' => empty($short_code['photo_more']) ? '' : $short_code['photo_more'],
880 'overlay-size' => $short_code['overlay_size'],
881 'overlay-video-size' => $short_code['overlay_video_size'],
882 ];
883
884 if (isset($album->SecurityType) && $album->SecurityType == 'Password') {
885 $object['classes'] = ['photonic-smug-passworded'];
886 $object['passworded'] = 1;
887 }
888
889 if (empty($named_albums) || (!empty($named_albums) && in_array($album->AlbumKey, $named_albums) && strtolower($short_code['filter_type']) !== 'exclude') ||
890 (!empty($named_albums) && !in_array($album->AlbumKey, $named_albums) && strtolower($short_code['filter_type']) === 'exclude')) {
891 $objects[] = $object;
892 }
893 }
894 }
895 }
896 return $objects;
897 }
898
899 /**
900 * Access Token URL
901 *
902 * @return string
903 */
904 public function access_token_URL() {
905 return 'http://api.smugmug.com/services/oauth/1.0a/getAccessToken';
906 }
907
908 /**
909 * Authenticate URL
910 *
911 * @return string
912 */
913 public function authenticate_URL() {
914 return 'http://api.smugmug.com/services/oauth/1.0a/authorize';
915 }
916
917 /**
918 * Authorize URL
919 *
920 * @return string
921 */
922 public function authorize_URL() {
923 return 'http://api.smugmug.com/services/oauth/1.0a/authorize';
924 }
925
926 /**
927 * Request Token URL
928 *
929 * @return string
930 */
931 public function request_token_URL() {
932 return 'http://api.smugmug.com/services/oauth/1.0a/getRequestToken';
933 }
934
935 /**
936 * Tests to see if the OAuth Access Token that is cached is still valid. This is important because a user might have manually revoked
937 * access for your app through the provider's control panel.
938 *
939 * @param $token
940 * @return array|WP_Error
941 */
942 function check_access_token($token) {
943 $signed_parameters = $this->sign_call($this->base_url.'user/sayontan', 'GET', []);
944 $end_point = $this->base_url.'user/sayontan?'.Authenticator::build_query($signed_parameters);
945 $response = Photonic::http($end_point, 'GET', null);
946
947 return $response;
948 }
949
950 /**
951 * Takes the response for the "Check access token", then tries to determine whether the check was successful or not.
952 *
953 * @param $response
954 * @return bool
955 */
956 public function is_access_token_valid($response) {
957 if (is_wp_error($response)) {
958 return false;
959 }
960
961 $response = $response['response'];
962 if ($response['code'] == 200) {
963 return true;
964 }
965 return false;
966 }
967 }
968