PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 2.19
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v2.19
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.19, at extensions/Photonic_Processor.php

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