PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 3.34
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v3.34
3.37 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 All 142 releases
photonic / Core / Photonic.php

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

842 lines 30.0 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 if (current_user_can('edit_theme_options')) {
310 $parent_slug = 'photonic-options-manager';
311 }
312 elseif (current_user_can('edit_posts')) {
313 $parent_slug = 'photonic-getting-started';
314 }
315
316 if (!empty($parent_slug)) {
317 add_menu_page('Photonic', 'Photonic', 'edit_posts', $parent_slug, [&$this->admin_menu, 'settings'], PHOTONIC_URL . 'include/images/Photonic-20-gr.png');
318 add_submenu_page($parent_slug, esc_html__('Settings', 'photonic'), esc_html__('Settings', 'photonic'), 'edit_theme_options', 'photonic-options-manager', [&$this->admin_menu, 'settings']);
319 add_submenu_page($parent_slug, 'Getting Started', 'Getting Started', 'edit_posts', 'photonic-getting-started', [&$this->admin_menu, 'getting_started']);
320 add_submenu_page($parent_slug, 'Authentication', 'Authentication', 'edit_theme_options', 'photonic-auth', [&$this->admin_menu, 'authentication']);
321 add_submenu_page($parent_slug, esc_html__('Shortcode Replacement', 'photonic'), esc_html__('Shortcode Replacement', 'photonic'), 'edit_posts', 'photonic-shortcode-replace', [&$this->admin_menu, 'shortcode']);
322 add_submenu_page($parent_slug, 'Helpers', 'Helpers', 'edit_posts', 'photonic-helpers', [&$this->admin_menu, 'helpers']);
323 }
324 }
325
326 /**
327 * Adds all scripts and their dependencies to the end of the <body> element only on pages using Photonic.
328 *
329 * @return void
330 */
331 public function conditionally_add_scripts() {
332 global $photonic_slideshow_library, $photonic_custom_lightbox_js, $photonic_custom_lightbox, $photonic_always_load_scripts,
333 $photonic_disable_photonic_lightbox_scripts, $photonic_disable_photonic_slider_scripts, $photonic_js_in_header;
334
335 $library_versions = [
336 'baguettebox' => '1.11.1',
337 'bigpicture' => '2022-03-31',
338 'colorbox' => '1.6.4',
339 'fancybox3' => '3.5.7',
340 'featherlight' => '1.7.14',
341 'glightbox' => '2022-03-12',
342 'imagelightbox' => '2018-08-17',
343 'lightcase' => '2.5.0',
344 'lightgallery' => '2.7.1',
345 'photoswipe' => '4.1.3',
346 'photoswipe5' => '5.3.7',
347 'prettyphoto' => '3.1.6',
348 'spotlight' => '0.7.8',
349 'splide' => '4.1.4',
350 'strip' => '1.8.0',
351 'swipebox' => '1.5.2',
352 'venobox' => '2.0.4',
353 ];
354
355 $requires_jq = [
356 'colorbox',
357 'fancybox',
358 'fancybox2',
359 'fancybox3',
360 'featherlight',
361 'imagelightbox',
362 'lightcase',
363 'magnific',
364 'prettyphoto',
365 'strip',
366 'swipebox',
367 ];
368
369 $photonic_dependencies = [];
370 $lb_deps = [];
371 if (in_array(self::$library, $requires_jq, true)) {
372 $photonic_dependencies[] = 'jquery';
373 $lb_deps[] = 'jquery';
374 }
375
376 if (in_array(self::$library, ['colorbox', 'fancybox', 'fancybox2', 'prettyphoto'], true)) {
377 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));
378 $photonic_dependencies[] = 'jquery-detect-swipe';
379 }
380
381 if ('thickbox' === self::$library) {
382 wp_enqueue_script('thickbox');
383 $photonic_dependencies[] = 'thickbox';
384 }
385 elseif ('custom' === $photonic_slideshow_library && 'strip' !== $photonic_custom_lightbox) {
386 $counter = 1;
387 $dependencies = ['jquery'];
388 foreach (preg_split("/((\r?\n)|(\r\n?))/", $photonic_custom_lightbox_js) as $line) {
389 wp_enqueue_script('photonic-lightbox-' . $counter, trim($line), $dependencies, PHOTONIC_VERSION, !($photonic_always_load_scripts && $photonic_js_in_header));
390 $photonic_dependencies[] = 'photonic-lightbox-' . $counter;
391 $counter++;
392 }
393 }
394 elseif ('none' !== self::$library) {
395 if (empty($photonic_disable_photonic_lightbox_scripts)) {
396 $photonic_dependencies[] = self::$library;
397 }
398
399 if (empty($photonic_disable_photonic_lightbox_scripts)) {
400 if ('lightgallery' === self::$library) {
401 $lightgallery_plugins = self::get_lightgallery_plugins();
402 if (!empty($lightgallery_plugins)) {
403 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));
404 $photonic_dependencies[] = 'lightgallery';
405 }
406 if (!empty(PHOTONIC_DEV_MODE)) {
407 foreach ($lightgallery_plugins as $plugin) {
408 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));
409 }
410 }
411 else {
412 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));
413 }
414 }
415 elseif ('photoswipe5' === self::$library) {
416 wp_deregister_script('photoswipe'); // Remove any older version of PhotoSwipe, since the new version is not compatible with it
417 }
418 }
419 }
420
421 if (empty($photonic_disable_photonic_slider_scripts)) {
422 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));
423 $photonic_dependencies[] = 'splide';
424 }
425
426 $slideshow_library = self::$library;
427
428 if (empty($photonic_disable_photonic_lightbox_scripts) && 'none' !== $slideshow_library && 'thickbox' !== $slideshow_library && $slideshow_library !== $photonic_custom_lightbox/* && 'photoswipe5' !== $slideshow_library*/) {
429 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));
430 }
431
432 $module = "include/js/front-end/out/photonic-" . $slideshow_library . PHOTONIC_DEV_MODE . '.js';
433
434 wp_enqueue_script('photonic', PHOTONIC_URL . $module, $photonic_dependencies, $this->get_version(PHOTONIC_PATH . "/" . $module), !($photonic_always_load_scripts && $photonic_js_in_header));
435
436 $this->localize_variables_once();
437 }
438
439 /**
440 * Special function to ensure that wp_localize_script, defining Photonic_JS is called at the most once.
441 * Since <code>conditionally_add_scripts</code> is called from <code>modify_gallery</code>, it can include the Photonic_JS
442 * definition multiple times. This code ensures that it is included just once.
443 */
444 public function localize_variables_once() {
445 if ($this->localized) {
446 return;
447 }
448 // Technically JS, but needs to happen here, otherwise the script is repeated multiple times, once for each time
449 // <code>conditionally_add_scripts</code> is called.
450 require_once PHOTONIC_PATH . '/Core/Front_End.php';
451 $js_array = Front_End::get_instance()->get_localized_js_variables();
452 wp_localize_script('photonic', 'Photonic_JS', $js_array);
453 $this->localized = true;
454 }
455
456 /**
457 * Adds all styles to all pages because styles, if not added in the header can cause issues.
458 *
459 * @return void
460 */
461 public function always_add_styles() {
462 global $photonic_slideshow_library, $photonic_custom_lightbox_css, $photonic_disable_photonic_lightbox_scripts, $photonic_disable_photonic_slider_scripts;
463
464 if ('custom' === $photonic_slideshow_library) {
465 $counter = 1;
466 foreach (preg_split("/((\r?\n)|(\r\n?))/", $photonic_custom_lightbox_css) as $line) {
467 wp_enqueue_style('photonic-lightbox-' . $counter, trim($line), [], PHOTONIC_VERSION);
468 $counter++;
469 }
470 }
471
472 $slideshow_library = esc_attr(!empty($photonic_disable_photonic_lightbox_scripts) ? 'none' : self::$library);
473
474 $this->enqueue_lightbox_styles($slideshow_library, empty($photonic_disable_photonic_slider_scripts));
475
476 global $photonic_css_in_file;
477 $file = trailingslashit(PHOTONIC_UPLOAD_DIR) . 'custom-styles.css';
478 if (@file_exists($file) && !empty($photonic_css_in_file)) { // phpcs:ignore WordPress.PHP.NoSilencedErrors
479 wp_enqueue_style('photonic-custom', trailingslashit(PHOTONIC_UPLOAD_URL) . 'custom-styles.css', ['photonic'], $this->get_version($file));
480 }
481 else {
482 wp_add_inline_style('photonic', $this->generate_css());
483 }
484
485 if (class_exists('\FLBuilder')) {
486 $this->load_beaver();
487 }
488 }
489
490 public function enqueue_lightbox_styles($slideshow_library = 'swipebox', $include_slider = true) {
491 if ($include_slider) {
492 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'));
493 }
494
495 $no_css = [
496 'bigpicture',
497
498 'none',
499 'fancybox',
500 'fancybox2',
501 'fancybox4',
502 'magnific',
503 'prettyphoto',
504 ];
505
506 if ('colorbox' === $slideshow_library) {
507 global $photonic_cbox_theme;
508 if ('theme' === $photonic_cbox_theme) {
509 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'));
510 }
511 else {
512 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'));
513 }
514 }
515 elseif ('lightgallery' === $slideshow_library) {
516 global $photonic_enable_lg_transitions;
517 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'));
518 if (!empty($photonic_enable_lg_transitions)) {
519 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'));
520 }
521 }
522 elseif ('thickbox' === $slideshow_library) {
523 wp_enqueue_style('thickbox');
524 }
525 elseif (!in_array($slideshow_library, $no_css, true)) {
526 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'));
527 }
528
529 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"));
530 }
531
532 /**
533 * Prints the dynamically generated CSS based on option selections.
534 *
535 * @param bool $header
536 * @return string
537 */
538 public function generate_css(bool $header = true): string {
539 global $photonic_tile_spacing, $photonic_masonry_tile_spacing, $photonic_mosaic_tile_spacing;
540
541 $css = '';
542 $saved_css = get_option('photonic_css');
543
544 if ($header && !empty($saved_css)) {
545 $css .= "/* Retrieved from saved CSS */\n";
546 $css .= $saved_css;
547 }
548 else {
549 require_once PHOTONIC_PATH . '/Core/Front_End.php';
550 $front_end = Front_End::get_instance();
551
552 if ($header) {
553 $css .= "/* Dynamically generated CSS */\n";
554 }
555 $css .= ".photonic-panel { " .
556 $front_end->get_bg_css('photonic_flickr_gallery_panel_background') .
557 " }\n";
558
559 $css .= ".photonic-random-layout .photonic-thumb { padding: " . esc_attr($photonic_tile_spacing) . "px}\n";
560 $css .= ".photonic-masonry-layout .photonic-thumb, .photonic-masonry-horizontal-layout .photonic-thumb { padding: " . esc_attr($photonic_masonry_tile_spacing) . "px}\n";
561 $css .= ".photonic-mosaic-layout .photonic-thumb { padding: " . esc_attr($photonic_mosaic_tile_spacing) . "px}\n";
562 }
563
564 return $css;
565 }
566
567 public static function get_version($file) {
568 return gmdate("Ymd-Gis", @filemtime($file)); // phpcs:ignore WordPress.PHP.NoSilencedErrors
569 }
570
571 public function admin_init(): void {
572 require_once PHOTONIC_PATH . "/Admin/Admin.php";
573
574 if (!empty($_REQUEST['page']) && // phpcs:ignore WordPress.Security.NonceVerification
575 in_array($_REQUEST['page'], ['photonic-options-manager', 'photonic-options', 'photonic-helpers', 'photonic-getting-started', 'photonic-auth', 'photonic-shortcode-replace'], true)) { // phpcs:ignore WordPress.Security.NonceVerification
576 require_once PHOTONIC_PATH . "/Admin/Admin_Menu.php";
577 $this->admin_menu = new Admin_Menu(__FILE__, $this);
578 }
579 }
580
581 public function add_extensions() {
582 require_once "Gallery.php";
583 require_once PHOTONIC_PATH . "/Platforms/Base.php";
584 require_once PHOTONIC_PATH . '/Layouts/Core_Layout.php';
585 }
586
587 /**
588 * Overrides the native gallery short code, and does a lot more.
589 *
590 * @param $content
591 * @param array|string $attr
592 * @return string
593 */
594 public function modify_gallery($content, $attr = []) {
595 global $photonic_disable_on_home_page, $photonic_disable_on_archives;
596 if ((is_archive() && !empty($photonic_disable_on_archives)) ||
597 (is_home() && !empty($photonic_disable_on_home_page))) {
598 return false;
599 }
600
601 global $photonic_alternative_shortcode;
602
603 // If an alternative shortcode is used, then $content has the shortcode attributes
604 if (!empty($photonic_alternative_shortcode)) {
605 $attr = $content;
606 }
607 if (empty($attr)) {
608 $attr = [];
609 }
610
611 $this->conditionally_add_scripts();
612 $images = $this->get_gallery_images($attr);
613
614 return wp_kses($images, self::$safe_tags);
615 }
616
617 /**
618 * Adds Photonic attributes to the native WP galleries. This cannot be called in <code>Photonic_Plugin\Platforms\Native</code> because
619 * that class is not initialised until a gallery of the native type is encountered
620 *
621 * @param array $out
622 * @param array $pairs Not used, but needed since this is for a standard gallery filter.
623 * @param array $attributes
624 * @return mixed
625 */
626 public function native_gallery_attributes(array $out, array $pairs, array $attributes): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter
627 global $photonic_wp_title_caption, $photonic_thumbnail_style, $photonic_alternative_shortcode;
628
629 $defaults = [
630 'layout' => esc_attr($photonic_thumbnail_style ?: 'square'),
631
632 'custom_classes' => '',
633 'alignment' => '',
634
635 'caption' => esc_attr($photonic_wp_title_caption),
636 'page' => 1,
637 'count' => -1,
638 'thumb_size' => 'thumbnail',
639 'slide_size' => 'large',
640 ];
641
642 $attributes = array_merge($defaults, $attributes);
643 if (empty($attributes['style']) || ('default' === $attributes['style'] && !empty($photonic_alternative_shortcode) && 'gallery' !== $photonic_alternative_shortcode)) {
644 $attributes['style'] = $attributes['layout'];
645 }
646
647 foreach ($attributes as $key => $value) {
648 $out[$key] = $value;
649 }
650 return $out;
651 }
652
653 /**
654 * @param array $attr
655 * @return string
656 */
657 public function helper_shortcode(array $attr = []): string {
658 if (empty($attr)) {
659 $attr = [];
660 }
661
662 $this->conditionally_add_scripts();
663
664 if (empty($attr['type']) || !in_array(strtolower($attr['type']), ['google', 'flickr', 'smugmug', 'zenfolio'], true)) {
665 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>');
666 }
667
668 $gallery = new Gallery($attr);
669 return $gallery->get_helper_contents();
670 }
671
672 /**
673 * @param array $attr
674 * @return string
675 */
676 public function get_gallery_images(array $attr): string {
677 require_once PHOTONIC_PATH . '/Core/Front_End.php';
678 return Front_End::get_instance()->get_gallery_images($attr);
679 }
680
681 /**
682 * Make an HTTP request
683 *
684 * @static
685 * @param string $url
686 * @param string $method GET | POST.
687 * @param array|null $post_fields
688 * @param string|null $user_agent
689 * @param int $timeout
690 * @param bool $ssl_verify_peer
691 * @param array $headers
692 * @param array $cookies
693 * @return array|WP_Error
694 */
695 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 = []) {
696 $curl_args = [
697 'user-agent' => $user_agent,
698 'timeout' => $timeout,
699 'sslverify' => $ssl_verify_peer,
700 'headers' => array_merge(['Expect:'], $headers),
701 'method' => $method,
702 'body' => $post_fields,
703 'cookies' => $cookies,
704 ];
705
706 return wp_remote_request($url, $curl_args);
707 }
708
709 public function enable_translations() {
710 load_plugin_textdomain('photonic');
711 }
712
713 /**
714 * @param string|array $classes
715 * @return array
716 */
717 public function body_class($classes = []) {
718 if (!is_array($classes)) {
719 $classes = explode(' ', $classes);
720 }
721
722 return $classes;
723 }
724
725 /**
726 * Used for handling the front-end for Gutenberg blocks
727 *
728 * @param $attributes
729 * @return string
730 */
731 public function render_block($attributes): string {
732 if (!empty($attributes['shortcode'])) {
733 $shortcode = (array) (json_decode($attributes['shortcode']));
734
735 if (!empty($attributes['align'])) {
736 $shortcode['alignment'] = esc_attr($attributes['align']);
737 }
738 if (!empty($attributes['className'])) {
739 $shortcode['custom_classes'] = esc_attr($attributes['className']);
740 }
741
742 $this->conditionally_add_scripts();
743 return $this->get_gallery_images($shortcode);
744 }
745 return '';
746 }
747
748 private function add_gutenberg_support() {
749 if (function_exists('register_block_type')) {
750 register_block_type(
751 'photonic/gallery',
752 [
753 'attributes' => [
754 'shortcode' => [
755 'type' => 'string',
756 ],
757 ],
758 'render_callback' => [&$this, 'render_block'],
759 ]
760 );
761 }
762 }
763
764 public function curl_timeout($handle) {
765 // Forcing phpcs:ignore here, since the explicit purpose is to change cURL's timeout.
766 curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, PHOTONIC_CURL_TIMEOUT); // phpcs:ignore WordPress.WP.AlternativeFunctions
767 curl_setopt($handle, CURLOPT_TIMEOUT, max(PHOTONIC_CURL_TIMEOUT, 30)); // phpcs:ignore WordPress.WP.AlternativeFunctions
768 }
769
770 public static function log($element) {
771 if (PHOTONIC_DEBUG) {
772 echo wp_kses($element, self::$safe_tags);
773 }
774 }
775
776 /**
777 * @param $link
778 * @return string
779 */
780 public static function doc_link($link): string {
781 return ' ' . sprintf(esc_html__('See %1$shere%2$s for documentation.', 'photonic'), "<a href='$link'>", '</a>');
782 }
783
784 public function load_widget() {
785 require_once PHOTONIC_PATH . '/Add_Ons/WP/Widget.php';
786 register_widget("Photonic_Plugin\Add_Ons\WP\Widget");
787 }
788
789 public function load_beaver() {
790 require_once PHOTONIC_PATH . '/Add_Ons/Beaver/Beaver_Module.php';
791 if (class_exists('\FLBuilderModel') && \FLBuilderModel::is_builder_active()) {
792 $this->enqueue_widget_scripts();
793 }
794 }
795
796 public static function enqueue_widget_scripts() {
797 global $photonic_alternative_shortcode;
798 $js_array = [
799 'ajaxurl' => admin_url('admin-ajax.php'),
800 'shortcode' => esc_js($photonic_alternative_shortcode ?: 'gallery'),
801 'current_shortcode' => esc_html__('Current shortcode', 'photonic'),
802 'edit_message' => esc_html__('Click on the icon to edit your gallery.', 'photonic'),
803 ];
804 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);
805 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);
806 wp_localize_script('photonic-widget', 'Photonic_Widget_JS', $js_array);
807 wp_enqueue_style('photonic-widget', PHOTONIC_URL . 'include/css/admin/widget.css', [], self::get_version(PHOTONIC_PATH . '/include/css/admin/widget.css'));
808 }
809
810 /**
811 * 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.
812 *
813 * @param $styles
814 * @return mixed
815 */
816 public function safe_styles($styles) {
817 $styles[] = '--dw';
818 $styles[] = '--dh';
819 $styles[] = '--tile-min-height';
820 $styles[] = 'display';
821 return $styles;
822 }
823
824 public static function get_lightgallery_plugins(): array {
825 global $photonic_enable_lg_zoom, $photonic_enable_lg_thumbnail, $photonic_enable_lg_fullscreen, $photonic_enable_lg_autoplay;
826 $lightgallery_plugins = [];
827 if (!empty($photonic_enable_lg_autoplay)) {
828 $lightgallery_plugins[] = 'autoplay';
829 }
830 if (!empty($photonic_enable_lg_fullscreen)) {
831 $lightgallery_plugins[] = 'fullscreen';
832 }
833 if (!empty($photonic_enable_lg_thumbnail)) {
834 $lightgallery_plugins[] = 'thumbnail';
835 }
836 if (!empty($photonic_enable_lg_zoom)) {
837 $lightgallery_plugins[] = 'zoom';
838 }
839 return $lightgallery_plugins;
840 }
841 }
842