PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 3.36
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v3.36
3.36 3.35 3.34 3.33 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.40 2.41 2.42 2.43 2.44 All 141 releases
photonic / Core / Photonic.php

Photonic.php in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 3.36, at Core/Photonic.php

839 lines 29.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Photonic_Plugin\Core;
4
5 use Photonic_Plugin\Admin\Admin_Menu;
6 use Photonic_Plugin\Options\Defaults;
7 use Photonic_Plugin\Options\Options;
8 use WP_Error;
9
10 class Photonic {
11 public $defaults;
12 public bool $localized;
13 public array $provider_map;
14 public ?Admin_Menu $admin_menu;
15 public static string $library;
16 public static array $lightbox_replacements;
17 public static array $safe_tags;
18 public static array $safe_title_tags;
19 public static array $safe_description_tags;
20
21 public function __construct() {
22 // $start = microtime(true);
23 global $photonic_options;
24
25 self::$lightbox_replacements = [
26 'fancybox' => 'fancybox3',
27 'magnific' => 'venobox',
28 'prettyphoto' => 'spotlight',
29 'strip' => 'venobox',
30 ];
31
32 self::$safe_tags = array_merge_recursive(
33 [
34 // Videos
35 'video' => [
36 'width' => true,
37 'height' => true,
38 'class' => true,
39 'controls' => true,
40 'preload' => true,
41 'poster' => true,
42 ],
43
44 'source' => [
45 'src' => true,
46 'type' => true,
47 ],
48
49 // Password prompters
50 'input' => [
51 'type' => true,
52 'name' => true,
53 'id' => true,
54 'class' => true,
55 'value' => true,
56 'data-photonic-shortcode' => true,
57 ],
58
59 'button' => [
60 'class' => true,
61 ],
62
63 // Custom data attributes
64 'div' => [
65 'data-photonic' => true,
66 'data-photonic-gallery-columns' => true,
67 'data-photonic-query' => true,
68 'data-photonic-platform' => true,
69 'data-photonic-prompt' => true,
70
71 // Slideshow
72 'data-splide' => true,
73 ],
74
75 /*
76 'ul' => [
77 // Slideshows
78 'data-photonic-columns' => true,
79 'data-photonic-controls' => true,
80 'data-photonic-fx' => true,
81 'data-photonic-layout' => true,
82 'data-photonic-pause' => true,
83 'data-photonic-speed' => true,
84 'data-photonic-strip-style' => true,
85 'data-photonic-timeout' => true,
86 ],
87 */
88
89 'img' => [
90 // Lazy loading
91 'data-src' => true,
92
93 // Tooltips
94 'data-photonic-tooltip' => true,
95 ],
96
97 'a' => [
98 // Non-photonic
99 'data-html5-href' => true,
100 'data-title' => true,
101 'data-type' => true,
102
103 // Non-Photonic - BaguetteBox
104 'data-content-type' => true,
105
106 // Non-Photonic - BigPicture
107 'data-bp' => true,
108 'data-bp-type' => true,
109
110 // Non-Photonic - Fancybox
111 'data-fancybox' => true,
112
113 // Non-Photonic - Featherlight
114 'data-featherlight' => true,
115 'data-featherlight-type' => true,
116
117 // Non-Photonic - GLightbox
118 'data-format' => true,
119
120 // Non-Photonic - Lightcase
121 'data-lc-options' => true,
122
123 // Non-Photonic - LightGallery
124 'data-download-url' => true,
125 'data-video' => true,
126 'data-sub-html' => true,
127 'data-photonic-thumb' => true,
128
129 // Non-Photonic - PhotoSwipe5
130 'data-pswp-height' => true,
131 'data-pswp-width' => true,
132
133 // Non-Photonic - Spotlight
134 'data-media' => true,
135 'data-src-mp4' => true,
136 'data-poster' => true,
137
138 // Non-Photonic - Strip
139 'data-strip-group' => true,
140 'data-strip-group-options' => true,
141 'data-strip-caption' => true,
142
143 // Non-Photonic - VenoBox
144 'data-gall' => true,
145 'data-vbtype' => true,
146
147 // Tooltips
148 'data-photonic-tooltip' => true,
149
150 // Level 3
151 'data-photonic-layout' => true,
152 'data-photonic-level-3' => true,
153
154 // Photonic photos
155 'data-photonic-deep' => true,
156 'data-photonic-media-type' => true,
157 'data-rel' => true,
158
159 // Photonic albums, common
160
161 // Albums, Google
162
163 // Photos, SmugMug
164 'data-photonic-buy' => true,
165
166 // Albums, Zenfolio
167 'data-photonic-realm' => true,
168 ],
169
170 'figure' => [
171 // Layouts - Horizontal Masonry
172 'data-photonic-idx' => true,
173 ],
174 ],
175 wp_kses_allowed_html('post')
176 );
177
178 self::$safe_title_tags = [
179 'h4' => [],
180 ];
181
182 self::$safe_description_tags = [
183 'strong' => [],
184 'em' => [],
185 'b' => [],
186 'i' => [],
187 'br' => [],
188 'p' => [],
189 ];
190
191 require_once PHOTONIC_PATH . "/Options/Options.php";
192 add_action('admin_init', [Options::get_instance(), 'prepare_options'], 20); // Setting to 20 so that CPTs can be picked up - Utilities are loaded with a priority 10
193
194 $this->localized = false;
195 $this->provider_map = [
196 'flickr' => 'Flickr',
197 'smug' => 'SmugMug',
198 'smugmug' => 'SmugMug',
199 'google' => 'Google',
200 'zenfolio' => 'Zenfolio',
201 'instagram' => 'Instagram',
202 'deviantart' => 'DeviantArt'
203 ];
204
205 add_action('admin_menu', [&$this, 'add_admin_menu']);
206 add_action('admin_init', [&$this, 'admin_init']);
207
208 $photonic_options = get_option('photonic_options');
209 $set_options = isset($photonic_options) && is_array($photonic_options) ? $photonic_options : [];
210
211 $defaults = Defaults::get_options();
212 $all_options = array_merge($defaults, $set_options);
213
214 foreach ($all_options as $key => $value) {
215 $mod_key = 'photonic_' . $key;
216 global ${$mod_key};
217 ${$mod_key} = $value; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
218 }
219
220 define('PHOTONIC_SSL_VERIFY', empty($photonic_ssl_verify_off));
221 define('PHOTONIC_DEBUG', !empty($photonic_debug_on));
222
223 if (!empty($photonic_script_dev_mode)) {
224 define('PHOTONIC_DEV_MODE', '');
225 }
226 else {
227 define('PHOTONIC_DEV_MODE', '.min');
228 }
229
230 if (!empty($photonic_curl_timeout) && is_numeric($photonic_curl_timeout)) {
231 define('PHOTONIC_CURL_TIMEOUT', $photonic_curl_timeout);
232 }
233 else {
234 define('PHOTONIC_CURL_TIMEOUT', 30);
235 }
236
237 global $photonic_slideshow_library, $photonic_custom_lightbox;
238 if ('custom' !== $photonic_slideshow_library) {
239 self::$library = esc_attr($photonic_slideshow_library);
240 self::$library = empty(self::$lightbox_replacements[self::$library]) ? self::$library : self::$lightbox_replacements[self::$library];
241 }
242 elseif (empty($photonic_slideshow_library)) {
243 self::$library = 'baguettebox';
244 }
245 else {
246 self::$library = esc_attr($photonic_custom_lightbox);
247 }
248
249 // Gallery
250 if (!empty($photonic_alternative_shortcode)) {
251 add_shortcode($photonic_alternative_shortcode, [&$this, 'modify_gallery']);
252 add_filter('shortcode_atts_' . $photonic_alternative_shortcode, [&$this, 'native_gallery_attributes'], 10, 3);
253 }
254 else {
255 add_filter('post_gallery', [&$this, 'modify_gallery'], 20, 2);
256 add_filter('shortcode_atts_gallery', [&$this, 'native_gallery_attributes'], 10, 3);
257 }
258
259 add_shortcode('photonic_helper', [&$this, 'helper_shortcode']);
260
261 add_action('wp_enqueue_scripts', [&$this, 'always_add_styles'], 20);
262 if (!empty($photonic_always_load_scripts)) {
263 add_action('wp_enqueue_scripts', [&$this, 'conditionally_add_scripts'], 20, 0);
264 }
265
266 require_once PHOTONIC_PATH . "/Core/AJAX.php";
267 AJAX::get_instance($this);
268
269 /*
270 add_action('photonic_token_monitor', [&$this, 'monitor_token_validity']);
271 if (!wp_next_scheduled('photonic_token_monitor')) {
272 wp_schedule_event(time(), 'hourly', 'photonic_token_monitor');
273 }
274 */
275 // The above code was commented out in March 2023, Photonic v 2.85, to prevent running the cron for Instagram.
276 // The code below was added to clean out any previously scheduled cron jobs.
277 // This will be removed not before March 2024, to give users the opportunity to install the plugin and have it un-schedule their jobs.
278 // $photonic_token_monitor_timestamp = wp_next_scheduled('photonic_token_monitor');
279 // wp_unschedule_event($photonic_token_monitor_timestamp, 'photonic_token_monitor');
280
281 $this->add_extensions();
282 $this->add_gutenberg_support();
283
284 add_action('http_api_curl', [&$this, 'curl_timeout'], 100);
285
286 add_action('plugins_loaded', [&$this, 'enable_translations']);
287
288 add_filter('body_class', [&$this, 'body_class']);
289
290 add_filter('safe_style_css', [&$this, 'safe_styles']);
291
292 // $end = microtime(true);
293 // print_r("<!-- Photonic initialization: ".($end - $start)." -->\n");
294
295 add_action('widgets_init', [&$this, 'load_widget']);
296
297 // add_action('elementor/common/after_register_scripts', [&$this, 'enqueue_widget_scripts']);
298 add_action('elementor/editor/before_enqueue_scripts', [&$this, 'enqueue_widget_scripts']);
299
300 require_once PHOTONIC_PATH . "/Core/Template.php";
301 }
302
303 /**
304 * Adds a menu item to the "Settings" section of the admin page.
305 *
306 * @return void
307 */
308 public function add_admin_menu() {
309 require_once PHOTONIC_PATH . "/Admin/Admin_Menu.php";
310 $this->admin_menu = new Admin_Menu(__FILE__, $this);
311
312 if (current_user_can('edit_theme_options')) {
313 $parent_slug = 'photonic-options-manager';
314 }
315 elseif (current_user_can('edit_posts')) {
316 $parent_slug = 'photonic-getting-started';
317 }
318
319 if (!empty($parent_slug)) {
320 add_menu_page('Photonic', 'Photonic', 'edit_posts', $parent_slug, [&$this->admin_menu, 'settings'], PHOTONIC_URL . 'include/images/Photonic-20-gr.png');
321 add_submenu_page($parent_slug, esc_html__('Settings', 'photonic'), esc_html__('Settings', 'photonic'), 'edit_theme_options', 'photonic-options-manager', [&$this->admin_menu, 'settings']);
322 add_submenu_page($parent_slug, 'Getting Started', 'Getting Started', 'edit_posts', 'photonic-getting-started', [&$this->admin_menu, 'getting_started']);
323 add_submenu_page($parent_slug, 'Authentication', 'Authentication', 'edit_theme_options', 'photonic-auth', [&$this->admin_menu, 'authentication']);
324 add_submenu_page($parent_slug, esc_html__('Shortcode Replacement', 'photonic'), esc_html__('Shortcode Replacement', 'photonic'), 'edit_posts', 'photonic-shortcode-replace', [&$this->admin_menu, 'shortcode']);
325 add_submenu_page($parent_slug, 'Helpers', 'Helpers', 'edit_posts', 'photonic-helpers', [&$this->admin_menu, 'helpers']);
326 }
327 }
328
329 /**
330 * Adds all scripts and their dependencies to the end of the <body> element only on pages using Photonic.
331 *
332 * @return void
333 */
334 public function conditionally_add_scripts() {
335 global $photonic_slideshow_library, $photonic_custom_lightbox_js, $photonic_custom_lightbox, $photonic_always_load_scripts,
336 $photonic_disable_photonic_lightbox_scripts, $photonic_disable_photonic_slider_scripts, $photonic_js_in_header;
337
338 $library_versions = [
339 'baguettebox' => '1.11.1',
340 'bigpicture' => '2022-03-31',
341 'colorbox' => '1.6.4',
342 'fancybox3' => '3.5.7',
343 'featherlight' => '1.7.14',
344 'glightbox' => '2022-03-12',
345 'imagelightbox' => '2018-08-17',
346 'lightcase' => '2.5.0',
347 'lightgallery' => '2.7.1',
348 'photoswipe' => '4.1.3',
349 'photoswipe5' => '5.3.7',
350 'prettyphoto' => '3.1.6',
351 'spotlight' => '0.7.8',
352 'splide' => '4.1.4',
353 'strip' => '1.8.0',
354 'swipebox' => '1.5.2',
355 'venobox' => '2.0.4',
356 ];
357
358 $requires_jq = [
359 'colorbox',
360 'fancybox',
361 'fancybox2',
362 'fancybox3',
363 'featherlight',
364 'imagelightbox',
365 'lightcase',
366 'magnific',
367 'prettyphoto',
368 'strip',
369 'swipebox',
370 ];
371
372 $photonic_dependencies = [];
373 $lb_deps = [];
374 if (in_array(self::$library, $requires_jq, true)) {
375 $photonic_dependencies[] = 'jquery';
376 $lb_deps[] = 'jquery';
377 }
378
379 if (in_array(self::$library, ['colorbox', 'fancybox', 'fancybox2', 'prettyphoto'], true)) {
380 wp_enqueue_script('jquery-detect-swipe', PHOTONIC_URL . 'include/ext/jquery.detect_swipe.js', ['jquery'], $this->get_version(PHOTONIC_PATH . '/include/ext/jquery.detect_swipe.js'), !($photonic_always_load_scripts && $photonic_js_in_header));
381 $photonic_dependencies[] = 'jquery-detect-swipe';
382 }
383
384 if ('thickbox' === self::$library) {
385 wp_enqueue_script('thickbox');
386 $photonic_dependencies[] = 'thickbox';
387 }
388 elseif ('custom' === $photonic_slideshow_library && 'strip' !== $photonic_custom_lightbox) {
389 $counter = 1;
390 $dependencies = ['jquery'];
391 foreach (preg_split("/((\r?\n)|(\r\n?))/", $photonic_custom_lightbox_js) as $line) {
392 wp_enqueue_script('photonic-lightbox-' . $counter, trim($line), $dependencies, PHOTONIC_VERSION, !($photonic_always_load_scripts && $photonic_js_in_header));
393 $photonic_dependencies[] = 'photonic-lightbox-' . $counter;
394 $counter++;
395 }
396 }
397 elseif ('none' !== self::$library) {
398 if (empty($photonic_disable_photonic_lightbox_scripts)) {
399 $photonic_dependencies[] = self::$library;
400 }
401
402 if (empty($photonic_disable_photonic_lightbox_scripts)) {
403 if ('lightgallery' === self::$library) {
404 $lightgallery_plugins = self::get_lightgallery_plugins();
405 if (!empty($lightgallery_plugins)) {
406 wp_enqueue_script('lightgallery', PHOTONIC_URL . 'include/ext/' . self::$library . '/' . self::$library . PHOTONIC_DEV_MODE . '.js', $lb_deps, $this->get_version(PHOTONIC_PATH . '/include/ext/' . self::$library . '/' . self::$library . PHOTONIC_DEV_MODE . '.js'), !($photonic_always_load_scripts && $photonic_js_in_header));
407 $photonic_dependencies[] = 'lightgallery';
408 }
409 if (!empty(PHOTONIC_DEV_MODE)) {
410 foreach ($lightgallery_plugins as $plugin) {
411 wp_enqueue_script('photonic-lightbox-' . $plugin, PHOTONIC_URL . 'include/ext/' . self::$library . '/lg-plugin-' . $plugin . '.min.js', ['lightgallery'], $this->get_version(PHOTONIC_PATH . '/include/ext/' . self::$library . '/lg-plugin-' . $plugin . '.min.js'), !($photonic_always_load_scripts && $photonic_js_in_header));
412 }
413 }
414 else {
415 wp_enqueue_script('photonic-lightbox-plugins', PHOTONIC_URL . 'include/ext/' . self::$library . '/lightgallery-plugins.js', ['lightgallery'], $this->get_version(PHOTONIC_PATH . '/include/ext/' . self::$library . '/lightgallery-plugins.js'), !($photonic_always_load_scripts && $photonic_js_in_header));
416 }
417 }
418 elseif ('photoswipe5' === self::$library) {
419 wp_deregister_script('photoswipe'); // Remove any older version of PhotoSwipe, since the new version is not compatible with it
420 }
421 }
422 }
423
424 if (empty($photonic_disable_photonic_slider_scripts)) {
425 wp_enqueue_script('splide', PHOTONIC_URL . 'include/ext/splide/splide' . PHOTONIC_DEV_MODE . '.js', [], $library_versions['splide'] . '-' . $this->get_version(PHOTONIC_PATH . '/include/ext/splide/splide' . PHOTONIC_DEV_MODE . '.js'), !($photonic_always_load_scripts && $photonic_js_in_header));
426 $photonic_dependencies[] = 'splide';
427 }
428
429 $slideshow_library = self::$library;
430
431 if (empty($photonic_disable_photonic_lightbox_scripts) && 'none' !== $slideshow_library && 'thickbox' !== $slideshow_library && $slideshow_library !== $photonic_custom_lightbox/* && 'photoswipe5' !== $slideshow_library*/) {
432 wp_enqueue_script($slideshow_library, PHOTONIC_URL . 'include/ext/' . $slideshow_library . '/' . $slideshow_library . PHOTONIC_DEV_MODE . '.js', $lb_deps, (empty($library_versions[$slideshow_library]) ? $this->get_version(PHOTONIC_PATH . "/include/ext/$slideshow_library/$slideshow_library" . PHOTONIC_DEV_MODE . ".js") : $library_versions[$slideshow_library]), !($photonic_always_load_scripts && $photonic_js_in_header));
433 }
434
435 $module = "include/js/front-end/out/photonic-" . $slideshow_library . PHOTONIC_DEV_MODE . '.js';
436
437 wp_enqueue_script('photonic', PHOTONIC_URL . $module, $photonic_dependencies, $this->get_version(PHOTONIC_PATH . "/" . $module), !($photonic_always_load_scripts && $photonic_js_in_header));
438
439 $this->localize_variables_once();
440 }
441
442 /**
443 * Special function to ensure that wp_localize_script, defining Photonic_JS is called at the most once.
444 * Since <code>conditionally_add_scripts</code> is called from <code>modify_gallery</code>, it can include the Photonic_JS
445 * definition multiple times. This code ensures that it is included just once.
446 */
447 public function localize_variables_once() {
448 if ($this->localized) {
449 return;
450 }
451 // Technically JS, but needs to happen here, otherwise the script is repeated multiple times, once for each time
452 // <code>conditionally_add_scripts</code> is called.
453 require_once PHOTONIC_PATH . '/Core/Front_End.php';
454 $js_array = Front_End::get_instance()->get_localized_js_variables();
455 wp_localize_script('photonic', 'Photonic_JS', $js_array);
456 $this->localized = true;
457 }
458
459 /**
460 * Adds all styles to all pages because styles, if not added in the header can cause issues.
461 *
462 * @return void
463 */
464 public function always_add_styles() {
465 global $photonic_slideshow_library, $photonic_custom_lightbox_css, $photonic_disable_photonic_lightbox_scripts, $photonic_disable_photonic_slider_scripts;
466
467 if ('custom' === $photonic_slideshow_library) {
468 $counter = 1;
469 foreach (preg_split("/((\r?\n)|(\r\n?))/", $photonic_custom_lightbox_css) as $line) {
470 wp_enqueue_style('photonic-lightbox-' . $counter, trim($line), [], PHOTONIC_VERSION);
471 $counter++;
472 }
473 }
474
475 $slideshow_library = esc_attr(!empty($photonic_disable_photonic_lightbox_scripts) ? 'none' : self::$library);
476
477 $this->enqueue_lightbox_styles($slideshow_library, empty($photonic_disable_photonic_slider_scripts));
478
479 global $photonic_css_in_file;
480 $file = trailingslashit(PHOTONIC_UPLOAD_DIR) . 'custom-styles.css';
481 if (@file_exists($file) && !empty($photonic_css_in_file)) { // phpcs:ignore WordPress.PHP.NoSilencedErrors
482 wp_enqueue_style('photonic-custom', trailingslashit(PHOTONIC_UPLOAD_URL) . 'custom-styles.css', ['photonic'], $this->get_version($file));
483 }
484 else {
485 wp_add_inline_style('photonic', $this->generate_css());
486 }
487
488 if (class_exists('\FLBuilder')) {
489 $this->load_beaver();
490 }
491 }
492
493 public function enqueue_lightbox_styles($slideshow_library = 'swipebox', $include_slider = true) {
494 if ($include_slider) {
495 wp_enqueue_style('photonic-slider', PHOTONIC_URL . 'include/ext/splide/splide' . PHOTONIC_DEV_MODE . '.css', [], $this->get_version(PHOTONIC_PATH . '/include/ext/splide/splide' . PHOTONIC_DEV_MODE . '.css'));
496 }
497
498 $no_css = [
499 'bigpicture',
500
501 'none',
502 'fancybox',
503 'fancybox2',
504 'fancybox4',
505 'magnific',
506 'prettyphoto',
507 ];
508
509 if ('colorbox' === $slideshow_library) {
510 global $photonic_cbox_theme;
511 if ('theme' === $photonic_cbox_theme) {
512 wp_enqueue_style('photonic-lightbox', PHOTONIC_URL . 'include/ext/colorbox/style-1/colorbox.css', [], $this->get_version(PHOTONIC_PATH . '/include/ext/colorbox/style-1/colorbox.css'));
513 }
514 else {
515 wp_enqueue_style('photonic-lightbox', PHOTONIC_URL . 'include/ext/colorbox/style-' . $photonic_cbox_theme . '/colorbox.css', [], $this->get_version(PHOTONIC_PATH . '/include/ext/colorbox/style-' . $photonic_cbox_theme . '/colorbox.css'));
516 }
517 }
518 elseif ('lightgallery' === $slideshow_library) {
519 global $photonic_enable_lg_transitions;
520 wp_enqueue_style('photonic-lightbox', PHOTONIC_URL . 'include/ext/lightgallery/lightgallery' . PHOTONIC_DEV_MODE . '.css', [], $this->get_version(PHOTONIC_PATH . '/include/ext/lightgallery/lightgallery' . PHOTONIC_DEV_MODE . '.css'));
521 if (!empty($photonic_enable_lg_transitions)) {
522 wp_enqueue_style('photonic-lightbox-lg-transitions', PHOTONIC_URL . 'include/ext/lightgallery/lightgallery-transitions.min.css', [], $this->get_version(PHOTONIC_PATH . '/include/ext/lightgallery/lightgallery-transitions.min.css'));
523 }
524 }
525 elseif ('thickbox' === $slideshow_library) {
526 wp_enqueue_style('thickbox');
527 }
528 elseif (!in_array($slideshow_library, $no_css, true)) {
529 wp_enqueue_style('photonic-lightbox', PHOTONIC_URL . 'include/ext/' . $slideshow_library . '/' . $slideshow_library . PHOTONIC_DEV_MODE . '.css', [], $this->get_version(PHOTONIC_PATH . '/include/ext/' . $slideshow_library . '/' . $slideshow_library . PHOTONIC_DEV_MODE . '.css'));
530 }
531
532 wp_enqueue_style('photonic', PHOTONIC_URL . "include/css/front-end/core/photonic" . PHOTONIC_DEV_MODE . ".css", [], $this->get_version(PHOTONIC_PATH . "/include/css/front-end/core/photonic" . PHOTONIC_DEV_MODE . ".css"));
533 }
534
535 /**
536 * Prints the dynamically generated CSS based on option selections.
537 *
538 * @param bool $header
539 * @return string
540 */
541 public function generate_css(bool $header = true): string {
542 global $photonic_tile_spacing, $photonic_masonry_tile_spacing, $photonic_mosaic_tile_spacing;
543
544 $css = '';
545 $saved_css = get_option('photonic_css');
546
547 if ($header && !empty($saved_css)) {
548 $css .= "/* Retrieved from saved CSS */\n";
549 $css .= $saved_css;
550 }
551 else {
552 require_once PHOTONIC_PATH . '/Core/Front_End.php';
553 $front_end = Front_End::get_instance();
554
555 if ($header) {
556 $css .= "/* Dynamically generated CSS */\n";
557 }
558 $css .= ".photonic-panel { " .
559 $front_end->get_bg_css('photonic_flickr_gallery_panel_background') .
560 " }\n";
561
562 $css .= ".photonic-random-layout .photonic-thumb { padding: " . esc_attr($photonic_tile_spacing) . "px}\n";
563 $css .= ".photonic-masonry-layout .photonic-thumb, .photonic-masonry-horizontal-layout .photonic-thumb { padding: " . esc_attr($photonic_masonry_tile_spacing) . "px}\n";
564 $css .= ".photonic-mosaic-layout .photonic-thumb { padding: " . esc_attr($photonic_mosaic_tile_spacing) . "px}\n";
565 }
566
567 return $css;
568 }
569
570 public static function get_version($file) {
571 return gmdate("Ymd-Gis", @filemtime($file)); // phpcs:ignore WordPress.PHP.NoSilencedErrors
572 }
573
574 public function admin_init(): void {
575 require_once PHOTONIC_PATH . "/Admin/Admin.php";
576 }
577
578 public function add_extensions() {
579 require_once "Gallery.php";
580 require_once PHOTONIC_PATH . "/Platforms/Base.php";
581 require_once PHOTONIC_PATH . '/Layouts/Core_Layout.php';
582 }
583
584 /**
585 * Overrides the native gallery short code, and does a lot more.
586 *
587 * @param $content
588 * @param array|string $attr
589 * @return string
590 */
591 public function modify_gallery($content, $attr = []) {
592 global $photonic_disable_on_home_page, $photonic_disable_on_archives;
593 if ((is_archive() && !empty($photonic_disable_on_archives)) ||
594 (is_home() && !empty($photonic_disable_on_home_page))) {
595 return false;
596 }
597
598 global $photonic_alternative_shortcode;
599
600 // If an alternative shortcode is used, then $content has the shortcode attributes
601 if (!empty($photonic_alternative_shortcode)) {
602 $attr = $content;
603 }
604 if (empty($attr)) {
605 $attr = [];
606 }
607
608 $this->conditionally_add_scripts();
609 $images = $this->get_gallery_images($attr);
610
611 return wp_kses($images, self::$safe_tags);
612 }
613
614 /**
615 * Adds Photonic attributes to the native WP galleries. This cannot be called in <code>Photonic_Plugin\Platforms\Native</code> because
616 * that class is not initialised until a gallery of the native type is encountered
617 *
618 * @param array $out
619 * @param array $pairs Not used, but needed since this is for a standard gallery filter.
620 * @param array $attributes
621 * @return mixed
622 */
623 public function native_gallery_attributes(array $out, array $pairs, array $attributes): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter
624 global $photonic_wp_title_caption, $photonic_thumbnail_style, $photonic_alternative_shortcode;
625
626 $defaults = [
627 'layout' => esc_attr($photonic_thumbnail_style ?: 'square'),
628
629 'custom_classes' => '',
630 'alignment' => '',
631
632 'caption' => esc_attr($photonic_wp_title_caption),
633 'page' => 1,
634 'count' => -1,
635 'thumb_size' => 'thumbnail',
636 'slide_size' => 'large',
637 ];
638
639 $attributes = array_merge($defaults, $attributes);
640 if (empty($attributes['style']) || ('default' === $attributes['style'] && !empty($photonic_alternative_shortcode) && 'gallery' !== $photonic_alternative_shortcode)) {
641 $attributes['style'] = $attributes['layout'];
642 }
643
644 foreach ($attributes as $key => $value) {
645 $out[$key] = $value;
646 }
647 return $out;
648 }
649
650 /**
651 * @param array $attr
652 * @return string
653 */
654 public function helper_shortcode(array $attr = []): string {
655 if (empty($attr)) {
656 $attr = [];
657 }
658
659 $this->conditionally_add_scripts();
660
661 if (empty($attr['type']) || !in_array(strtolower($attr['type']), ['google', 'flickr', 'smugmug', 'zenfolio'], true)) {
662 return sprintf(esc_html__('Please specify a value for %1$s. Accepted values are %2$s, %3$s, %4$s, %5$s', 'photonic'), '<code>type</code>', '<code>google</code>', '<code>flickr</code>', '<code>smugmug</code>', '<code>zenfolio</code>');
663 }
664
665 $gallery = new Gallery($attr);
666 return $gallery->get_helper_contents();
667 }
668
669 /**
670 * @param array $attr
671 * @return string
672 */
673 public function get_gallery_images(array $attr): string {
674 require_once PHOTONIC_PATH . '/Core/Front_End.php';
675 return Front_End::get_instance()->get_gallery_images($attr);
676 }
677
678 /**
679 * Make an HTTP request
680 *
681 * @static
682 * @param string $url
683 * @param string $method GET | POST.
684 * @param array|null $post_fields
685 * @param string|null $user_agent
686 * @param int $timeout
687 * @param bool $ssl_verify_peer
688 * @param array $headers
689 * @param array $cookies
690 * @return array|WP_Error
691 */
692 public static function http(string $url, string $method = 'POST', ?array $post_fields = null, ?string $user_agent = null, int $timeout = 90, bool $ssl_verify_peer = false, array $headers = [], array $cookies = []) {
693 $curl_args = [
694 'user-agent' => $user_agent,
695 'timeout' => $timeout,
696 'sslverify' => $ssl_verify_peer,
697 'headers' => array_merge(['Expect:'], $headers),
698 'method' => $method,
699 'body' => $post_fields,
700 'cookies' => $cookies,
701 ];
702
703 return wp_remote_request($url, $curl_args);
704 }
705
706 public function enable_translations() {
707 load_plugin_textdomain('photonic');
708 }
709
710 /**
711 * @param string|array $classes
712 * @return array
713 */
714 public function body_class($classes = []) {
715 if (!is_array($classes)) {
716 $classes = explode(' ', $classes);
717 }
718
719 return $classes;
720 }
721
722 /**
723 * Used for handling the front-end for Gutenberg blocks
724 *
725 * @param $attributes
726 * @return string
727 */
728 public function render_block($attributes): string {
729 if (!empty($attributes['shortcode'])) {
730 $shortcode = (array) (json_decode($attributes['shortcode']));
731
732 if (!empty($attributes['align'])) {
733 $shortcode['alignment'] = esc_attr($attributes['align']);
734 }
735 if (!empty($attributes['className'])) {
736 $shortcode['custom_classes'] = esc_attr($attributes['className']);
737 }
738
739 $this->conditionally_add_scripts();
740 return $this->get_gallery_images($shortcode);
741 }
742 return '';
743 }
744
745 private function add_gutenberg_support() {
746 if (function_exists('register_block_type')) {
747 register_block_type(
748 'photonic/gallery',
749 [
750 'attributes' => [
751 'shortcode' => [
752 'type' => 'string',
753 ],
754 ],
755 'render_callback' => [&$this, 'render_block'],
756 ]
757 );
758 }
759 }
760
761 public function curl_timeout($handle) {
762 // Forcing phpcs:ignore here, since the explicit purpose is to change cURL's timeout.
763 curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, PHOTONIC_CURL_TIMEOUT); // phpcs:ignore WordPress.WP.AlternativeFunctions
764 curl_setopt($handle, CURLOPT_TIMEOUT, max(PHOTONIC_CURL_TIMEOUT, 30)); // phpcs:ignore WordPress.WP.AlternativeFunctions
765 }
766
767 public static function log($element) {
768 if (PHOTONIC_DEBUG) {
769 echo wp_kses($element, self::$safe_tags);
770 }
771 }
772
773 /**
774 * @param $link
775 * @return string
776 */
777 public static function doc_link($link): string {
778 return ' ' . sprintf(esc_html__('See %1$shere%2$s for documentation.', 'photonic'), "<a href='$link'>", '</a>');
779 }
780
781 public function load_widget() {
782 require_once PHOTONIC_PATH . '/Add_Ons/WP/Widget.php';
783 register_widget("Photonic_Plugin\Add_Ons\WP\Widget");
784 }
785
786 public function load_beaver() {
787 require_once PHOTONIC_PATH . '/Add_Ons/Beaver/Beaver_Module.php';
788 if (class_exists('\FLBuilderModel') && \FLBuilderModel::is_builder_active()) {
789 $this->enqueue_widget_scripts();
790 }
791 }
792
793 public static function enqueue_widget_scripts() {
794 global $photonic_alternative_shortcode;
795 $js_array = [
796 'ajaxurl' => admin_url('admin-ajax.php'),
797 'shortcode' => esc_js($photonic_alternative_shortcode ?: 'gallery'),
798 'current_shortcode' => esc_html__('Current shortcode', 'photonic'),
799 'edit_message' => esc_html__('Click on the icon to edit your gallery.', 'photonic'),
800 ];
801 wp_enqueue_script('photonic-native-ui', PHOTONIC_URL . 'include/js/admin/native-ui.js', ['shortcode', 'thickbox'], self::get_version(PHOTONIC_PATH . '/include/js/admin/native-ui.js'), false);
802 wp_enqueue_script('photonic-widget', PHOTONIC_URL . 'include/js/admin/widget.js', ['photonic-native-ui'], self::get_version(PHOTONIC_PATH . '/include/js/admin/widget.js'), true);
803 wp_localize_script('photonic-widget', 'Photonic_Widget_JS', $js_array);
804 wp_enqueue_style('photonic-widget', PHOTONIC_URL . 'include/css/admin/widget.css', [], self::get_version(PHOTONIC_PATH . '/include/css/admin/widget.css'));
805 }
806
807 /**
808 * Custom style attributes, primarily required for the Justified Grid layout. Since <code>wp_kses_post</code> strips out tags that it doesn't recognize, we have this.
809 *
810 * @param $styles
811 * @return mixed
812 */
813 public function safe_styles($styles) {
814 $styles[] = '--dw';
815 $styles[] = '--dh';
816 $styles[] = '--tile-min-height';
817 $styles[] = 'display';
818 return $styles;
819 }
820
821 public static function get_lightgallery_plugins(): array {
822 global $photonic_enable_lg_zoom, $photonic_enable_lg_thumbnail, $photonic_enable_lg_fullscreen, $photonic_enable_lg_autoplay;
823 $lightgallery_plugins = [];
824 if (!empty($photonic_enable_lg_autoplay)) {
825 $lightgallery_plugins[] = 'autoplay';
826 }
827 if (!empty($photonic_enable_lg_fullscreen)) {
828 $lightgallery_plugins[] = 'fullscreen';
829 }
830 if (!empty($photonic_enable_lg_thumbnail)) {
831 $lightgallery_plugins[] = 'thumbnail';
832 }
833 if (!empty($photonic_enable_lg_zoom)) {
834 $lightgallery_plugins[] = 'zoom';
835 }
836 return $lightgallery_plugins;
837 }
838 }
839