PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 2.32
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v2.32
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_Processor.php

Photonic_Processor.php in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 2.32, at extensions/Photonic_Processor.php

675 lines 22.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Gallery processor class to be extended by individual processors. This class has an abstract method called <code>get_gallery_images</code>
4 * that has to be defined by each inheriting processor.
5 *
6 * This is also where the OAuth support is implemented. The URLs are defined using abstract functions, while a handful of utility functions are defined.
7 * Most utility functions have been adapted from the OAuth PHP package distributed here: https://code.google.com/p/oauth-php/.
8 *
9 * @package Photonic
10 * @subpackage Extensions
11 */
12
13 abstract class Photonic_Processor {
14 public $library, $thumb_size, $full_size, $api_key, $api_secret, $provider, $nonce, $oauth_timestamp, $signature_parameters, $link_lightbox_title, $layout,
15 $oauth_version, $oauth_done, $show_more_link, $is_server_down, $is_more_required, $login_shown, $login_box_counter, $gallery_index, $bypass_popup, $common_parameters,
16 $doc_links, $password_protected, $token, $token_secret, $show_buy_link, $stack_trace;
17
18 function __construct() {
19 global $photonic_slideshow_library, $photonic_custom_lightbox, $photonic_enable_popup, $photonic_thumbnail_style;
20 if ($photonic_slideshow_library != 'custom') {
21 $this->library = $photonic_slideshow_library;
22 }
23 else {
24 $this->library = $photonic_custom_lightbox;
25 }
26 $this->nonce = Photonic_Processor::nonce();
27 $this->oauth_timestamp = time();
28 $this->oauth_version = '1.0';
29 $this->show_more_link = false;
30 $this->is_server_down = false;
31 $this->is_more_required = true;
32 $this->login_shown = false;
33 $this->login_box_counter = 0;
34 $this->gallery_index = 0;
35 $this->bypass_popup = !isset($photonic_enable_popup) || $photonic_enable_popup === false || $photonic_enable_popup == '' || $photonic_enable_popup == 'off';
36 $this->common_parameters = [
37 'columns' => 'auto',
38 'layout' => !empty($photonic_thumbnail_style) ? $photonic_thumbnail_style : 'square',
39 'more' => '',
40 'display' => 'in-page',
41 'panel' => '',
42 'filter' => '',
43 'filter_type' => 'include',
44 'fx' => 'slide', // LightSlider effects: fade and slide
45 'timeout' => 4000, // Time between slides in ms
46 'speed' => 1000, // Time for each transition
47 'pause' => true, // Pause on hover
48 'strip-style' => 'thumbs',
49 'controls' => 'show',
50 'popup' => $this->bypass_popup ? 'hide' : 'show',
51
52 'custom_classes' => '',
53 'alignment' => '',
54 ];
55
56 $this->doc_links = [];
57 $this->password_protected = esc_html__('This album is password-protected. Please provide a valid password.', 'photonic');
58 $this->show_buy_link = false;
59 $this->stack_trace = [];
60 $this->add_hooks();
61 }
62
63 /**
64 * Main function that fetches the images associated with the shortcode. This is implemented by all sub-classes.
65 *
66 * @abstract
67 * @param array $attr
68 * @param array $gallery_meta
69 */
70 abstract protected function get_gallery_images($attr = [], &$gallery_meta = []);
71
72 public function oauth_signature_method() {
73 return 'HMAC-SHA1';
74 }
75
76 /**
77 * Takes a token response from a request token call, then puts it in an appropriate array.
78 *
79 * @param $response
80 * @return array
81 */
82 public function parse_token($response) {
83 return [];
84 }
85
86 public function save_token($token) {
87 $photonic_authentication = get_option('photonic_authentication');
88 if (!isset($photonic_authentication)) {
89 $photonic_authentication = [];
90 }
91 $photonic_authentication[$this->provider] = $token;
92 update_option('photonic_authentication', $photonic_authentication);
93 }
94
95 public function get_cached_token() {
96 $photonic_authentication = get_option('photonic_authentication');
97 if (!empty($photonic_authentication) && isset($photonic_authentication[$this->provider])) {
98 return $photonic_authentication[$this->provider];
99 }
100 return null;
101 }
102
103 /**
104 * Generates a nonce for use in signing calls.
105 *
106 * @static
107 * @return string
108 */
109 public static function nonce() {
110 $mt = microtime();
111 $rand = mt_rand();
112 return md5($mt . $rand);
113 }
114
115 /**
116 * Encodes the URL as per RFC3986 specs. This replaces some strings in addition to the ones done by a rawurlencode.
117 * This has been adapted from the OAuth for PHP project.
118 *
119 * @static
120 * @param $input
121 * @return array|mixed|string
122 */
123 public static function urlencode_rfc3986($input) {
124 if (is_array($input)) {
125 return array_map(['Photonic_Processor', 'urlencode_rfc3986'], $input);
126 }
127 else if (is_scalar($input)) {
128 return str_replace(
129 '+',
130 ' ',
131 str_replace('%7E', '~', rawurlencode($input))
132 );
133 }
134 else {
135 return '';
136 }
137 }
138
139 /**
140 * Takes an array of parameters, then parses it and generates a query string. Prior to generating the query string the parameters are sorted in their natural order.
141 * Without sorting the signatures between this application and the provider might differ.
142 *
143 * @static
144 * @param $params
145 * @return string
146 */
147 public static function build_query($params) {
148 if (!$params) {
149 return '';
150 }
151 $keys = array_map(['Photonic_Processor', 'urlencode_rfc3986'], array_keys($params));
152 $values = array_map(['Photonic_Processor', 'urlencode_rfc3986'], array_values($params));
153 $params = array_combine($keys, $values);
154
155 // Sort by keys (natsort)
156 uksort($params, 'strnatcmp');
157 $pairs = [];
158 foreach ($params as $key => $value) {
159 if (is_array($value)) {
160 natsort($value);
161 foreach ($value as $v2) {
162 $pairs[] = ($v2 == '') ? "$key=0" : "$key=$v2";
163 }
164 }
165 else {
166 $pairs[] = ($value == '') ? "$key=0" : "$key=$value";
167 }
168 }
169
170 $string = implode('&', $pairs);
171 return $string;
172 }
173
174 /**
175 * Takes a string of parameters in an HTML encoded string, then returns an array of name-value pairs, with the parameter
176 * name and the associated value.
177 *
178 * @static
179 * @param $input
180 * @return array
181 */
182 public static function parse_parameters($input) {
183 if (!isset($input) || !$input) return [];
184
185 $pairs = explode('&', $input);
186
187 $parsed_parameters = [];
188 foreach ($pairs as $pair) {
189 $split = explode('=', $pair, 2);
190 $parameter = urldecode($split[0]);
191 $value = isset($split[1]) ? urldecode($split[1]) : '';
192
193 if (isset($parsed_parameters[$parameter])) {
194 // We have already recieved parameter(s) with this name, so add to the list
195 // of parameters with this name
196 if (is_scalar($parsed_parameters[$parameter])) {
197 // This is the first duplicate, so transform scalar (string) into an array
198 // so we can add the duplicates
199 $parsed_parameters[$parameter] = [$parsed_parameters[$parameter]];
200 }
201
202 $parsed_parameters[$parameter][] = $value;
203 }
204 else {
205 $parsed_parameters[$parameter] = $value;
206 }
207 }
208 return $parsed_parameters;
209 }
210
211 /**
212 * If authentication is enabled for this processor and the user has not authenticated this site to access his profile,
213 * this shows a login box.
214 *
215 * @param $post_id
216 * @return string
217 */
218 public function get_login_box($post_id = '') {
219 $login_box_option = 'photonic_'.$this->provider.'_login_box';
220 $login_button_option = 'photonic_'.$this->provider.'_login_button';
221 global ${$login_box_option}, ${$login_button_option};
222 $login_box = ${$login_box_option};
223 $login_button = ${$login_button_option};
224 $this->login_box_counter++;
225 $ret = '<div id="photonic-login-box-'.$this->provider.'-'.$this->login_box_counter.'" class="photonic-login-box photonic-login-box-'.$this->provider.'">'."\n";
226 if ($this->is_server_down) {
227 $ret .= esc_html__("The authentication server is down. Please try after some time.", 'photonic');
228 }
229 else {
230 $ret .= "\t".wp_specialchars_decode($login_box, ENT_QUOTES)."\n";
231 if (trim($login_button) == '') {
232 $login_button = 'Login';
233 }
234 else {
235 $login_button = wp_specialchars_decode($login_button, ENT_QUOTES);
236 }
237
238 if (!empty($post_id)) {
239 $rel = "rel='auth-button-single-$post_id'";
240 }
241 else {
242 $rel = '';
243 }
244 $ret .= "\t<p class='photonic-auth-button'>\n\t\t<a href='#' class='auth-button auth-button-{$this->provider}' $rel>".$login_button."</a>\n\t</p>\n";
245 }
246 $ret .= "</div><!-- photonic-login-box -->\n";
247 return $ret;
248 }
249
250 function more_link_button($link_to = '') {
251 global $photonic_archive_link_more;
252 if (empty($photonic_archive_link_more) && $this->is_more_required) {
253 return "<div class='photonic-more-link-container'><a href='$link_to' class='photonic-more-button more-button-{$this->provider}'>See the rest</a></div>";
254 }
255 $this->is_more_required = true;
256 return '';
257 }
258
259 /**
260 * Prints the header for a section. Typically used for albums / photosets / groups, where some generic information about the album / photoset / group is available.
261 * The <code>$options</code> array accepts the following prarameters:
262 * - string type Indicates what type of object is being displayed like gallery / photoset / album etc. This is added to the CSS class.
263 * - array $hidden Contains the elements that should be hidden from the header display.
264 * - array $counters Contains counts of the object that the header represents. In most cases this has just one value. Zenfolio objects have multiple values.
265 * - string $link Should clicking on the thumbnail / title take you anywhere?
266 * - string $display Indicates if this is on the page or in a popup
267 * - bool $iterate_level_3 If this is a level 3 header, this field indicates whether an expansion icon should be shown. This is to improve performance for Flickr collections.
268 * - string $provider What is the source of the data?
269 *
270 * @param array $header The header object, which contains the title, thumbnail source URL and the link where clicking on the thumb will take you
271 * @param array $options The options to display this header. Options contain the listed internal fields fields
272 * @param array $gallery_meta
273 * @return string
274 */
275 function process_object_header($header, $options = [], &$gallery_meta = []) {
276 $type = empty($options['type']) ? 'group' : $options['type'];
277 $hidden = isset($options['hidden']) && is_array($options['hidden']) ? $options['hidden'] : [];
278 $counters = isset($options['counters']) && is_array($options['counters']) ? $options['counters'] : [];
279 $link = !isset($options['link']) ? true : $options['link'];
280 $display = empty($options['display']) ? 'in-page' : $options['display'];
281 $iterate_level_3 = !isset($options['iterate_level_3']) ? true : $options['iterate_level_3'];
282
283 if ($this->bypass_popup && $display != 'in-page') {
284 return '';
285 }
286 $ret = '';
287 if (!empty($header['title'])) {
288 global $photonic_external_links_in_new_tab;
289 $title = esc_attr($header['title']);
290
291 $gallery_meta['title'] = $title;
292 $gallery_meta['type'] = $type;
293
294 if (!empty($photonic_external_links_in_new_tab)) {
295 $target = ' target="_blank" ';
296 }
297 else {
298 $target = '';
299 }
300
301 $anchor = '';
302 if (!empty($header['thumb_url'])) {
303 $image = '<img src="'.esc_url($header['thumb_url']).'" alt="'.$title.'" />';
304
305 if ($link) {
306 $anchor = "<a href='".esc_url($header['link_url'])."' class='photonic-header-thumb photonic-{$this->provider}-$type-solo-thumb' title='".$title."' $target>".$image."</a>";
307 }
308 else {
309 $anchor = "<div class='photonic-header-thumb photonic-{$this->provider}-$type-solo-thumb'>$image</div>";
310 }
311 }
312
313 if (empty($hidden['thumbnail']) || empty($hidden['title']) || empty($hidden['counter']) || empty($iterate_level_3)) {
314 $popup_header_class = '';
315 if ($display == 'popup') {
316 $popup_header_class = 'photonic-panel-header';
317 }
318 $ret .= "<div class='photonic-object-header photonic-{$this->provider}-$type $popup_header_class'>";
319
320 if (empty($hidden['thumbnail'])) {
321 $ret .= $anchor;
322 }
323 if (empty($hidden['title']) || empty($hidden['counter']) || empty($iterate_level_3)) {
324 $ret .= "<div class='photonic-header-details photonic-$type-details'>";
325 if (empty($hidden['title']) || empty($iterate_level_3)) {
326 $provider = $this->provider;
327 $expand = empty($iterate_level_3) ? '<a href="#" title="'.esc_attr__('Show', 'photonic').'" class="photonic-level-3-expand photonic-level-3-expand-plus" data-photonic-level-3="'.$provider.'-'.$type.'-'.$header['id'].'" data-photonic-layout="'.$options['layout'].'">&nbsp;</a>' : '';
328
329 if ($link) {
330 $ret .= "<div class='photonic-header-title photonic-$type-title'><a href='".esc_url($header['link_url'])."' $target>".$title.'</a>'.$expand.'</div>';
331 }
332 else {
333 $ret .= "<div class='photonic-header-title photonic-$type-title'>".$title.$expand.'</div>';
334 }
335 }
336 if (empty($hidden['counter'])) {
337 $counter_texts = [];
338 if (!empty($counters['groups'])) {
339 $counter_texts[] = esc_html(sprintf(_n('%s group', '%s groups', $counters['groups'], 'photonic'), $counters['groups']));
340 }
341 if (!empty($counters['sets'])) {
342 $counter_texts[] = esc_html(sprintf(_n('%s set', '%s sets', $counters['sets'], 'photonic'), $counters['sets']));
343 }
344 if (!empty($counters['photos'])) {
345 $counter_texts[] = esc_html(sprintf(_n('%s photo', '%s photos', $counters['photos'], 'photonic'), $counters['photos']));
346 }
347 if (!empty($counters['videos'])) {
348 $counter_texts[] = esc_html(sprintf(_n('%s video', '%s videos', $counters['videos'], 'photonic'), $counters['videos']));
349 }
350
351 apply_filters('photonic_modify_counter_texts', $counter_texts, $counters);
352
353 if (!empty($counter_texts)) {
354 $ret .= "<span class='photonic-header-info photonic-$type-photos'>".implode(', ', $counter_texts).'</span>';
355 }
356 }
357
358 $ret .= "</div><!-- .photonic-$type-details -->";
359 }
360 $ret .= "</div>";
361 }
362 }
363
364 return $ret;
365 }
366
367 /**
368 * Generates the markup for a single photo.
369 *
370 * @param $provider string Name of the photo provider. A CSS class is created in the header, photonic-single-<code>$provider</code>-photo-header
371 * @param $data array Pertinent pieces of information about the photo - the source (src), the photo page (href), title and caption
372 * @return string
373 */
374 function generate_single_photo_markup($provider, $data) {
375 $ret = '';
376 $photo = array_merge(
377 ['src' => '', 'href' => '', 'title' => '', 'caption' => ''],
378 $data
379 );
380
381 if (empty($photo['src'])) {
382 return $ret;
383 }
384
385 global $photonic_external_links_in_new_tab;
386 if (!empty($photo['title'])) {
387 $ret .= "\t".'<h3 class="photonic-single-photo-header photonic-single-'.$provider.'-photo-header">'.$photo['title']."</h3>\n";
388 }
389
390 $img = '<img src="'.esc_url($photo['src']).'" alt="'.esc_attr(empty($photo['caption']) ? $photo['title'] : $photo['caption']).'" />';
391 if (!empty($photo['href'])) {
392 $img = '<a href="'.esc_url($photo['href']).'" title="'.esc_attr(empty($photo['caption']) ? $photo['title'] : $photo['caption']).'" '.
393 (!empty($photonic_external_links_in_new_tab) ? ' target="_blank" ' : '').'>'.$img.'</a>';
394 }
395
396 if (!empty($photo['caption'])) {
397 $ret .= "\t".'<div class="wp-caption">'."\n\t\t".$img."\n\t\t".'<div class="wp-caption-text">'.$photo['caption']."</div>\n\t</div><!-- .wp-caption -->\n";
398 }
399 else {
400 $ret .= $img;
401 }
402
403 return $ret;
404 }
405
406 /**
407 * Generates the HTML for the lowest level gallery, i.e. the photos. This is used for both, in-page and popup displays.
408 * This calls an individual layout generator for rendering the gallery.
409 * The code for the random layouts is handled in JS, but just the HTML markers for it are provided here.
410 *
411 * @param $photos
412 * @param array $options
413 * @param $short_code
414 * @return string
415 */
416 function display_level_1_gallery($photos, $options, $short_code) {
417 $layout = !empty($short_code['layout']) ? $short_code['layout'] : 'square';
418 $layout_manager = $this->get_layout_manager($layout);
419 $ret = $layout_manager->generate_level_1_gallery($photos, $options, $short_code, $this);
420 return $ret;
421 }
422
423 function display_level_2_gallery($objects, $options, $short_code) {
424 $layout = !isset($options['layout']) ? 'square' : $options['layout'];
425 $layout_manager = $this->get_layout_manager($layout);
426 $ret = $layout_manager->generate_level_2_gallery($objects, $options, $short_code, $this);
427 return $ret;
428 }
429
430 function finalize_markup($content, $short_code) {
431 if ($short_code['display'] != 'popup') {
432 $additional_classes = '';
433 if (!empty($short_code['custom_classes'])) {
434 $additional_classes = $short_code['custom_classes'];
435 }
436 if (!empty($short_code['alignment'])) {
437 $additional_classes .= ' align'.$short_code['alignment'];
438 }
439 $ret = "<div class='photonic-{$this->provider}-stream photonic-stream $additional_classes' id='photonic-{$this->provider}-stream-{$this->gallery_index}'>\n";
440 }
441 else {
442 $popup_id = "id='photonic-{$this->provider}-panel-" . $short_code['panel'] . "'";
443 $ret = "<div class='photonic-{$this->provider}-panel photonic-panel' $popup_id>\n";
444 }
445 $ret .= $content."\n";
446 $ret .= "</div><!-- .photonic-stream or .photonic-panel -->\n";
447 return $ret;
448 }
449
450 function get_layout_manager($layout) {
451 global $photonic_layout_manager_default, $photonic_layout_manager_slideshow;
452 if (in_array($layout, ['strip-above', 'strip-below', 'strip-right', 'no-strip'])) {
453 if (!isset($photonic_layout_manager_slideshow)) {
454 $photonic_layout_manager_slideshow = new Photonic_Layout_Slideshow();
455 }
456 $layout_manager = $photonic_layout_manager_slideshow;
457 }
458 else {
459 if (!isset($photonic_layout_manager_default)) {
460 $photonic_layout_manager_default = new Photonic_Layout();
461 }
462 $layout_manager = $photonic_layout_manager_default;
463 }
464 return $layout_manager;
465 }
466
467 function get_header_display($args) {
468 if (!isset($args['headers'])) {
469 return [
470 'thumbnail' => 'inherit',
471 'title' => 'inherit',
472 'counter' => 'inherit',
473 ];
474 }
475 else if (empty($args['headers'])) {
476 return [
477 'thumbnail' => 'none',
478 'title' => 'none',
479 'counter' => 'none',
480 ];
481 }
482 else {
483 $header_array = explode(',', $args['headers']);
484 return [
485 'thumbnail' => in_array('thumbnail', $header_array) ? 'show' : 'none',
486 'title' => in_array('title', $header_array) ? 'show' : 'none',
487 'counter' => in_array('counter', $header_array) ? 'show' : 'none',
488 ];
489 }
490 }
491
492 function get_hidden_headers($arg_headers, $setting_headers) {
493 return [
494 'thumbnail' => $arg_headers['thumbnail'] === 'inherit' ? $setting_headers['thumbnail'] : ($arg_headers['thumbnail'] === 'none' ? true : false),
495 'title' => $arg_headers['title'] === 'inherit' ? $setting_headers['title'] : ($arg_headers['title'] === 'none' ? true : false),
496 'counter' => $arg_headers['counter'] === 'inherit' ? $setting_headers['counter'] : ($arg_headers['counter'] === 'none' ? true : false),
497 ];
498 }
499
500 /**
501 * Wraps an error message in appropriately-styled markup for display in the front-end
502 *
503 * @param $message
504 * @return string
505 */
506 function error($message) {
507 return "<div class='photonic-error photonic-{$this->provider}-error'>\n\t<span class='photonic-error-icon photonic-icon'>&nbsp;</span>\n\t<div class='photonic-message'>\n\t\t$message\n\t</div>\n</div>\n";
508 }
509
510 /**
511 * Retrieves the error messages from a WP_Response object and formats them in a display-ready markup.
512 *
513 * @param WP_Error $response
514 * @param bool $server_msg
515 * @return string
516 */
517 function wp_error_message($response, $server_msg = true) {
518 $ret = '';
519 if ($server_msg) {
520 $ret = $this->get_server_error()."<br/>\n";
521 }
522 if (is_wp_error($response)) {
523 $messages = $response->get_error_messages();
524 $ret .= '<strong>'.esc_html(sprintf(_n('%s Message:', '%s Messages:', count($messages), 'photonic'), count($messages)))."</strong><br/>\n";
525 foreach ($messages as $message) {
526 $ret .= $message."<br>\n";
527 }
528 }
529 return $ret;
530 }
531
532 function push_to_stack($event) {
533 global $photonic_performance_logging;
534 if (empty($photonic_performance_logging)) {
535 return;
536 }
537
538 if (!isset($this->stack_trace[$this->gallery_index])) {
539 $events = [];
540 }
541 else {
542 $events = $this->stack_trace[$this->gallery_index];
543 }
544
545 $this->add_to_first_open_event($events, $event);
546 $this->stack_trace[$this->gallery_index] = $events;
547 }
548
549 private function add_to_first_open_event(&$events, $new_event) {
550 $found = false;
551 foreach ($events as $id => $event) {
552 if (isset($event['start']) && !isset($event['end'])) {
553 // Ongoing event. Need to add to this.
554 $found = true;
555 if (!isset($event['children'])) {
556 $children = [];
557 }
558 else {
559 $children = $event['children'];
560 }
561 $this->add_to_first_open_event($children, $new_event);
562 $event['children'] = $children;
563 $events[$id] = $event;
564 }
565 if ($found) {
566 break;
567 }
568 }
569 if (!$found) {
570 $events[] = [
571 'event' => $new_event,
572 'start' => microtime(true),
573 ];
574 }
575 }
576
577 function pop_from_stack() {
578 global $photonic_performance_logging;
579 if (empty($photonic_performance_logging)) {
580 return;
581 }
582
583 if (!isset($this->stack_trace[$this->gallery_index])) {
584 return;
585 }
586 else {
587 $events = $this->stack_trace[$this->gallery_index];
588 $this->pop_from_first_open_event($events);
589 $this->stack_trace[$this->gallery_index] = $events;
590 }
591 }
592
593 private function pop_from_first_open_event(&$events) {
594 $found = false;
595 foreach ($events as $id => $event) {
596 if (isset($event['start']) && !isset($event['end'])) {
597 // Ongoing event. Need to pop this or its open child
598 $found = true;
599 $found_child = false;
600 if (isset($event['children'])) {
601 $children = $event['children'];
602 $found_child = $this->pop_from_first_open_event($children);
603 $event['children'] = $children;
604 }
605 if (!$found_child) {
606 $event['end'] = microtime(true);
607 $event['time'] = $event['end'] - $event['start'];
608 }
609 $events[$id] = $event;
610 }
611 if ($found) {
612 break;
613 }
614 }
615 return $found;
616 }
617
618 function get_stack_markup() {
619 global $photonic_performance_logging;
620 if (empty($photonic_performance_logging)) {
621 return '';
622 }
623
624 $ret = '';
625 if (!empty($this->stack_trace[$this->gallery_index])) {
626 $ret = "<!--\n";
627 $ret .= "Stats for Provider: {$this->provider}, Gallery: {$this->gallery_index}\n";
628 $events = $this->stack_trace[$this->gallery_index];
629 $ret .= $this->get_nested_element($events);
630 $ret .= "-->\n";
631 }
632 return $ret;
633 }
634
635 private function get_nested_element($events, $indent = "\t") {
636 $ret = '';
637 foreach ($events as $trace) {
638 $trace_items = [];
639 foreach ($trace as $key => $trace_item) {
640 if ($key != 'children') {
641 $trace_items[] = strtoupper(substr($key, 0, 1)).substr($key, 1).': '.$trace_item;
642 }
643 }
644 $ret .= $indent.implode(', ', $trace_items)."\n";
645 if (!empty($trace['children'])) {
646 $ret .= $this->get_nested_element($trace['children'], $indent."\t");
647 }
648 }
649 return $ret;
650 }
651
652 function ssl_verify_peer(&$handle) {
653 curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
654 }
655
656 function get_server_error() {
657 return sprintf(esc_html__('There was an error connecting to %s. Please try again later.', 'photonic'), $this->provider);
658 }
659
660 /**
661 * Helper execution, implemented by child classes
662 *
663 * @param $args
664 * @return string
665 */
666 function execute_helper($args) {
667 // Blank method, to be overridden by child classes
668 return '';
669 }
670
671 function add_hooks() {
672 // Blank method, implemented by child classes, if required
673 }
674 }
675