PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more / 4.5.4
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more v4.5.4
4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.14 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.10 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.4.0 4.4.1 4.4.10 4.4.11 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1
embedpress / EmbedPress / Includes / Classes / Helper.php
embedpress / EmbedPress / Includes / Classes Last commit date
Analytics 2 months ago Database 1 month ago DynamicFieldResolver.php 1 month ago Elementor_Enhancer.php 6 months ago EmbedPress_Core_Installer.php 6 years ago EmbedPress_Notice.php 3 months ago EmbedPress_Plugin_Usage_Tracker.php 2 months ago Extend_CustomPlayer_Controls.php 1 month ago Extend_Elementor_Controls.php 1 year ago FeatureNoticeManager.php 8 months ago FeatureNotices.php 8 months ago Feature_Enhancer.php 1 month ago Helper.php 1 month ago Pdf_Thumbnail_Handler.php 2 months ago PermalinkHelper.php 10 months ago README_FEATURE_NOTICES.md 8 months ago
Helper.php
1716 lines
1 <?php
2
3 namespace EmbedPress\Includes\Classes;
4
5 use EmbedPress\Providers\TemplateLayouts\YoutubeLayout;
6 use EmbedPress\Shortcode;
7
8 use Elementor\Plugin;
9
10
11 if (!defined('ABSPATH')) {
12 exit;
13 } // Exit if accessed directly
14
15 class Helper
16 {
17
18 /**
19 * Parse a query string into an associative array.
20 *
21 * If multiple values are found for the same key, the value of that key
22 * value pair will become an array. This function does not parse nested
23 * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will
24 * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
25 *
26 * @param string $str Query string to parse
27 * @param int|bool $urlEncoding How the query string is encoded
28 *
29 * @return array
30 */
31
32 public function __construct()
33 {
34 add_action('wp_ajax_lock_content_form_handler', [$this, 'lock_content_form_handler']);
35 add_action('wp_ajax_nopriv_lock_content_form_handler', [$this, 'lock_content_form_handler']);
36
37 add_action('wp_ajax_embedpress_gutenberg_password_check', [$this, 'gutenberg_password_check']);
38 add_action('wp_ajax_nopriv_embedpress_gutenberg_password_check', [$this, 'gutenberg_password_check']);
39
40
41 add_action('wp_ajax_loadmore_data_handler', [$this, 'loadmore_data_handler']);
42 add_action('wp_ajax_nopriv_loadmore_data_handler', [$this, 'loadmore_data_handler']);
43
44
45 add_action('wp_ajax_fetch_video_description', [$this, 'ajax_video_popup_description']);
46 add_action('wp_ajax_nopriv_fetch_video_description', [$this, 'ajax_video_popup_description']);
47 }
48
49 public function ajax_video_popup_description()
50 {
51 if (isset($_POST['vid'])) {
52 $api_key = self::get_api_key();
53 $vid = sanitize_text_field($_POST['vid']);
54
55 $video_data = Helper::get_youtube_video_data($api_key, $vid);
56
57 if ($video_data) {
58 ob_start();
59 ?>
60 <div class="video-description">
61 <?php echo YoutubeLayout::generate_youtube_video_description($video_data); ?>
62 </div>
63 <?php
64 $description_html = ob_get_clean();
65 wp_send_json_success(['description' => $description_html]);
66 } else {
67 wp_send_json_error(['error' => 'Failed to fetch video data.']);
68 }
69 } else {
70 wp_send_json_error(['error' => 'Invalid video ID.']);
71 }
72 }
73
74 public static function get_api_key()
75 {
76 $settings = (array) get_option(EMBEDPRESS_PLG_NAME . ':youtube', []);
77 return !empty($settings['api_key']) ? $settings['api_key'] : '';
78 }
79
80 public static function parse_query($str, $urlEncoding = true)
81 {
82 $result = [];
83
84 if ($str === '') {
85 return $result;
86 }
87
88 if ($urlEncoding === true) {
89 $decoder = function ($value) {
90 return rawurldecode(str_replace('+', ' ', $value));
91 };
92 } elseif ($urlEncoding === PHP_QUERY_RFC3986) {
93 $decoder = 'rawurldecode';
94 } elseif ($urlEncoding === PHP_QUERY_RFC1738) {
95 $decoder = 'urldecode';
96 } else {
97 $decoder = function ($str) {
98 return $str;
99 };
100 }
101
102 foreach (explode('&', $str) as $kvp) {
103 $parts = explode('=', $kvp, 2);
104 $key = $decoder($parts[0]);
105 $value = isset($parts[1]) ? $decoder($parts[1]) : null;
106 if (!isset($result[$key])) {
107 $result[$key] = $value;
108 } else {
109 if (!is_array($result[$key])) {
110 $result[$key] = [$result[$key]];
111 }
112 $result[$key][] = $value;
113 }
114 }
115
116 return $result;
117 }
118 public static function get_pdf_renderer()
119 {
120 // $renderer = EMBEDPRESS_URL_ASSETS. 'pdf/web/viewer.html';
121
122 $renderer = admin_url('admin-ajax.php?action=get_viewer');
123
124 // @TODO; apply settings query args here
125 return $renderer;
126 }
127
128 public static function get_flipbook_renderer()
129 {
130 $renderer = admin_url('admin-ajax.php?action=get_flipbook_viewer');
131 return $renderer;
132 }
133
134 public static function get_extension_from_file_url($url)
135 {
136 $urlSplit = explode(".", $url);
137 $ext = end($urlSplit);
138 return $ext;
139 }
140
141
142 public static function is_instagram_feed($url)
143 {
144 return (bool) preg_match('~(?:https?://)?(?:www\.)?instagram\.com/(?!p/|reel/|tv/|stories/)[^/]+/?$~i', (string) $url);
145 }
146
147 public static function is_file_url($url)
148 {
149 $pattern = '/\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/i';
150 return preg_match($pattern, $url) === 1;
151 }
152
153 public static function is_opensea($url)
154 {
155 return strpos($url, "opensea.io") !== false;
156 }
157 public static function is_youtube_channel($url)
158 {
159 return (bool) (preg_match('~(?:https?:\/\/)?(?:www\.)?(?:youtube.com\/)(?:channel\/|c\/|user\/|@)(\w+)~i', (string) $url));
160 }
161
162 public static function is_youtube($url)
163 {
164 return (bool) (preg_match('~(?:https?://)?(?:www\.)?(?:youtube\.com|youtu\.be)/watch\?v=([^&]+)~i', (string) $url));
165 }
166
167 // Saved sources data temporary in wp_options table
168 public static function get_source_data($blockid, $source_url, $source_option_name, $source_temp_option_name)
169 {
170 if (self::is_youtube_channel($source_url)) {
171 $source_name = 'YoutubeChannel';
172 } else if (self::is_youtube($source_url)) {
173 $source_name = 'Youtube';
174 } else if (!empty(self::is_file_url($source_url))) {
175 $source_name = 'document_' . self::get_extension_from_file_url($source_url);
176 } else if (self::is_opensea($source_url)) {
177 $source_name = 'OpenSea';
178 } else if (self::is_instagram_feed($source_url)) {
179 $source_name = 'InstagramFeed';
180 } else {
181 Shortcode::get_embera_instance();
182 $collectios = Shortcode::get_collection();
183 $provider = $collectios->findProviders($source_url);
184
185 if (!empty($provider[$source_url])) {
186 $source_name = $provider[$source_url]->getProviderName();
187 } else {
188 $host = parse_url($source_url, PHP_URL_HOST);
189 if ($host) {
190 $parts = explode('.', $host);
191 if (count($parts) > 1) {
192 $source_name = $parts[1];
193 } else {
194 // Handle the case where the host doesn't have at least two parts
195 $source_name = $host;
196 }
197 } else {
198 // Handle the case where parse_url fails
199 $source_name = 'unknown';
200 }
201 }
202 }
203
204 if (!empty($blockid) && $blockid != 'undefined') {
205 $sources = json_decode(get_option($source_temp_option_name), true);
206
207 if (!$sources) {
208 $sources = array();
209 }
210 $exists = false;
211
212 foreach ($sources as $i => $source) {
213 if ($source['id'] === $blockid) {
214 $sources[$i]['source']['name'] = $source_name;
215 $sources[$i]['source']['url'] = $source_url;
216 $exists = true;
217 break;
218 }
219 }
220
221 if (!$exists) {
222 $sources[] = array('id' => $blockid, 'source' => array('name' => $source_name, 'url' => $source_url, 'count' => 1));
223 }
224
225 update_option($source_temp_option_name, json_encode($sources));
226 }
227 }
228
229 // Saved source data when post updated
230 public static function get_save_source_data_on_post_update($source_option_name, $source_temp_option_name)
231 {
232
233 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
234 return;
235 }
236 $temp_data = json_decode(get_option($source_temp_option_name), true);
237 $source_data = json_decode(get_option($source_option_name), true);
238 if (!$temp_data) {
239 $temp_data = array();
240 }
241 if (!$source_data) {
242 $source_data = array();
243 }
244
245 $sources = array_merge($temp_data, $source_data);
246
247 $unique_sources = array();
248 foreach ($sources as $source) {
249 $unique_sources[$source['id']] = $source;
250 }
251
252 $unique_sources = array_values($unique_sources);
253
254 delete_option($source_temp_option_name);
255
256 update_option($source_option_name, json_encode($unique_sources));
257 }
258
259 //Delete source temporary data when reload without update or publish
260 public static function get_delete_source_temp_data_on_reload($source_temp_option_name)
261 {
262 $source_temp_data = json_decode(get_option($source_temp_option_name), true);
263 if ($source_temp_data) {
264 delete_option($source_temp_option_name);
265 }
266 }
267
268 public static function get_file_title($url)
269 {
270 return get_the_title(attachment_url_to_postid($url));
271 }
272
273 public static function get_hash()
274 {
275 $hash_key = get_option(EMBEDPRESS_PLG_NAME . '_hash_key');
276 if (!$hash_key) {
277 $hash_key = wp_hash_password(wp_generate_password(30));
278 update_option(EMBEDPRESS_PLG_NAME . '_hash_key', $hash_key);
279 }
280 return $hash_key;
281 }
282
283 public function lock_content_form_handler() {
284 // print_r($embedHTML);
285
286 $client_id = isset($_POST['client_id']) ? sanitize_text_field($_POST['client_id']) : '';
287 $password = isset($_POST['password']) ? sanitize_text_field($_POST['password']) : '';
288 $post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
289
290 $epbase64 = get_post_meta( $post_id, 'ep_base_' .$client_id, true );
291 $hash_key = get_post_meta( $post_id, 'hash_key_' .$client_id, true );
292
293 // Set the decryption key and initialization vector (IV)
294 $key = Helper::get_hash();
295
296 // Decode the base64 encoded cipher
297 $cipher = base64_decode($epbase64);
298 // Decrypt the cipher using AES-128-CBC encryption
299
300 $wp_pass_key = hash('sha256', wp_salt(32) . md5($password));
301 $iv = substr($wp_pass_key, 0, 16);
302
303 if ($wp_pass_key === $hash_key) {
304
305 $embed = openssl_decrypt($cipher, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv) . '<script>
306 var now = new Date();
307 var time = now.getTime();
308 var expireTime = time + 1000 * 60 * 60 * 24 * 30;
309 now.setTime(expireTime);
310 document.cookie = "password_correct_'.esc_js($client_id).'='.esc_js($hash_key).'; expires=" + now.toUTCString() + "; path=/";
311 </script>';
312
313 }
314 else{
315 $embed = 0;
316 }
317
318 // Process the form data and return a response
319 $response = array(
320 'success' => true,
321 'password' => $password,
322 'embedHtml' => $embed,
323 'post_id' => $post_id
324 );
325
326 wp_send_json($response);
327
328 }
329
330 public function gutenberg_password_check()
331 {
332 $client_id = isset($_POST['client_id']) ? sanitize_text_field($_POST['client_id']) : '';
333 $password = isset($_POST['password']) ? sanitize_text_field($_POST['password']) : '';
334 $content_password = isset($_POST['content_password']) ? sanitize_text_field($_POST['content_password']) : '';
335
336 // Verify password
337 if ($password === $content_password) {
338 // Set cookie for authentication
339 $hash_pass = hash('sha256', wp_salt(32) . md5($password));
340 setcookie("password_correct_" . $client_id, $hash_pass, time() + 3600, '/');
341
342 $response = array(
343 'success' => true,
344 'message' => 'Password correct'
345 );
346 } else {
347 $response = array(
348 'success' => false,
349 'message' => 'Incorrect password'
350 );
351 }
352
353 wp_send_json($response);
354 }
355
356 public static function display_password_form($client_id = '', $embedHtml = '', $pass_hash_key = '', $attributes = [])
357 {
358 $lock_heading = !empty($attributes['lockHeading']) ? sanitize_text_field($attributes['lockHeading']) : '';
359 $lock_subheading = !empty($attributes['lockSubHeading']) ? sanitize_text_field($attributes['lockSubHeading']) : '';
360 $lock_error_message = !empty($attributes['lockErrorMessage']) ? sanitize_text_field($attributes['lockErrorMessage']) : '';
361 $footer_message = !empty($attributes['footerMessage']) ? sanitize_text_field($attributes['footerMessage']) : '';
362 $password_placeholder = !empty($attributes['passwordPlaceholder']) ? sanitize_text_field($attributes['passwordPlaceholder']) : '';
363 $button_text = !empty($attributes['submitButtonText']) ? sanitize_text_field($attributes['submitButtonText']) : '';
364 $unlocking_text = !empty($attributes['submitUnlockingText']) ? sanitize_text_field($attributes['submitUnlockingText']) : '';
365 $enable_footer_message = !empty($attributes['enableFooterMessage']) ? sanitize_text_field($attributes['enableFooterMessage']) : '';
366
367
368 // Set the encryption key and initialization vector (IV)
369 $key = self::get_hash();
370
371 $salt = wp_salt(32);
372 $wp_hash_key = hash('sha256', $salt . $pass_hash_key);
373 $iv = substr($wp_hash_key, 0, 16);
374
375
376 // Encrypt the plaintext using AES-128-CBC encryption
377 $cipher = openssl_encrypt($embedHtml, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
378
379 // Base64 encode the encrypted cipher
380 $encrypted_data = base64_encode($cipher);
381
382 update_post_meta(get_the_ID(), 'ep_base_' . $client_id, $encrypted_data);
383 update_post_meta(get_the_ID(), 'hash_key_' . $client_id, $wp_hash_key);
384
385 $lock_icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><g fill="#6354a5" class="color134563 svgShape"><path d="M46.3 28.7h-3v-6.4C43.3 16.1 38.2 11 32 11c-6.2 0-11.3 5.1-11.3 11.3v6.4h-3v-6.4C17.7 14.4 24.1 8 32 8s14.3 6.4 14.3 14.3v6.4" fill="#6354a5" class="color000000 svgShape"></path><path d="M44.8 55.9H19.2c-2.6 0-4.8-2.2-4.8-4.8V31.9c0-2.6 2.2-4.8 4.8-4.8h25.6c2.6 0 4.8 2.2 4.8 4.8v19.2c0 2.7-2.2 4.8-4.8 4.8zM19.2 30.3c-.9 0-1.6.7-1.6 1.6v19.2c0 .9.7 1.6 1.6 1.6h25.6c.9 0 1.6-.7 1.6-1.6V31.9c0-.9-.7-1.6-1.6-1.6H19.2z" fill="#6354a5" class="color000000 svgShape"></path><path d="M35.2 36.7c0 1.8-1.4 3.2-3.2 3.2s-3.2-1.4-3.2-3.2 1.4-3.2 3.2-3.2 3.2 1.5 3.2 3.2" fill="#6354a5" class="color000000 svgShape"></path><path d="M32.8 36.7h-1.6l-1.6 9.6h4.8l-1.6-9.6" fill="#6354a5" class="color000000 svgShape"></path></g></svg>';
386
387 echo '
388 <div class="password-form-container sd">
389 <h2>' . esc_html($lock_heading) . '</h2>
390 <p>' . esc_html($lock_subheading) . ' </p>
391 <form class="password-form" method="post" class="password-form" data-unlocking-text="' . esc_attr($unlocking_text) . '">
392
393 <div class="password-field">
394 <span class="lock-icon">' . $lock_icon . '</span>
395 <input type="password" name="pass_' . esc_attr($client_id) . '" placeholder="' . esc_attr($password_placeholder) . '" required>
396 </div>
397 <input type="hidden" name="ep_client_id" value="' . esc_attr($client_id) . '">
398 <input type="hidden" name="post_id" value="' . esc_attr(get_the_ID()) . '">
399
400 <input type="submit" name="password_submit" value="' . esc_attr($button_text) . '">
401 <div class="error-message hidden">' . esc_html($lock_error_message) . '</div>
402 </form>
403 ' . (!empty($enable_footer_message) ? '<p class="need-access-message">' . esc_html($footer_message) . '</p>' : '') . '
404 </div>
405 ';
406 }
407
408 // Check if the user has already entered the correct password
409 public static function is_password_correct($client_id)
410 {
411 if (isset($_COOKIE['password_correct_' . $client_id])) {
412 return $_COOKIE['password_correct_' . $client_id];
413 } else {
414 return false;
415 }
416 }
417
418 public static function customLogo($embedHTML, $atts)
419 {
420 $x = !empty($atts['logoX']) ? $atts['logoX'] : 0;
421 $y = !empty($atts['logoY']) ? $atts['logoY'] : 0;
422 $uniqid = !empty($atts['url']) ? '.ose-uid-' . md5($atts['url']) : '';
423
424 $brandUrl = !empty($atts['customlogoUrl']) ? $atts['customlogoUrl'] : '';
425 $opacity = !empty($atts['logoOpacity']) ? $atts['logoOpacity'] : '';
426
427 $cssClass = !empty($atts['url']) ? '.ose-uid-' . md5($atts['url']) : '.ose-youtube';
428
429
430
431 ob_start(); ?>
432 <style type="text/css">
433 <?php echo esc_html($cssClass); ?> {
434 position: relative;
435 }
436
437 <?php echo esc_html($cssClass); ?>.watermark {
438 border: 0;
439 position: absolute;
440 bottom: <?php echo esc_html($y); ?>%;
441 right: <?php echo esc_html($x); ?>%;
442 max-width: 150px;
443 max-height: 75px;
444 opacity: 0.25;
445 z-index: 5;
446 -o-transition: opacity 0.5s ease-in-out;
447 -moz-transition: opacity 0.5s ease-in-out;
448 -webkit-transition: opacity 0.5s ease-in-out;
449 transition: opacity 0.5s ease-in-out;
450 opacity: <?php echo esc_html($opacity); ?>;
451 }
452
453 <?php echo esc_html($cssClass); ?>.watermark:hover {
454 opacity: 1;
455 }
456 </style>
457 <?php
458
459
460 $style = ob_get_clean();
461
462 if (!class_exists('\simple_html_dom')) {
463 include_once EMBEDPRESS_PATH_CORE . 'simple_html_dom.php';
464 }
465
466 $cta = '';
467 $img = '';
468
469 if (!empty($atts['customlogo'])) {
470 $img = '<img src="' . esc_url($atts['customlogo']) . '"/>';
471
472 $imgDom = str_get_html($img);
473 $imgDom = $imgDom->find('img', 0);
474 $imgDom->setAttribute('class', 'watermark ep-custom-logo');
475 $imgDom->removeAttribute('style');
476 $imgDom->setAttribute('width', 'auto');
477 $imgDom->setAttribute('height', 'auto');
478 ob_start();
479 echo $imgDom;
480
481 $cta .= ob_get_clean();
482
483 $imgDom->clear();
484 unset($img, $imgDom);
485
486 if (!empty($brandUrl)) {
487 $cta = '<a href="' . esc_url($brandUrl) . '" target="_blank">' . $cta . '</a>';
488 }
489 $dom = str_get_html($embedHTML);
490
491 $wrapDiv = $dom->find($uniqid, 0);
492
493 if (!empty($wrapDiv) && is_object($wrapDiv)) {
494 $wrapDiv->innertext .= $cta;
495 }
496
497 ob_start();
498 echo $wrapDiv;
499
500 $markup = ob_get_clean();
501
502 $dom->clear();
503 unset($dom, $wrapDiv);
504
505 $embedHTML = $style . $markup;
506 }
507
508 return $embedHTML;
509 }
510
511
512 public static function embed_content_share($content_id = '', $attributes = [])
513 {
514 $share_position = !empty($attributes['sharePosition']) ? $attributes['sharePosition'] : 'right';
515 $custom_thumnail = !empty($attributes['customThumbnail']) ? $attributes['customThumbnail'] : '';
516 $custom_title = !empty($attributes['customTitle']) ? $attributes['customTitle'] : '';
517 $custom_description = !empty($attributes['customDescription']) ? $attributes['customDescription'] : '';
518
519 // Create a unique hash based on content attributes
520 $content_hash = md5($custom_thumnail . $custom_title . $custom_description . $content_id);
521
522 // Encode for URL usage
523 $custom_thumnail = urlencode($custom_thumnail);
524 $custom_title = urlencode($custom_title);
525 $custom_description = urlencode($custom_description);
526
527 // Get social share options with defaults
528 $facebook_enabled = isset($attributes['shareFacebook']) ? $attributes['shareFacebook'] !== false : true;
529 $twitter_enabled = isset($attributes['shareTwitter']) ? $attributes['shareTwitter'] !== false : true;
530 $pinterest_enabled = isset($attributes['sharePinterest']) ? $attributes['sharePinterest'] !== false : true;
531 $linkedin_enabled = isset($attributes['shareLinkedin']) ? $attributes['shareLinkedin'] !== false : true;
532 $style = isset($attributes['width']) ? 'style="max-width: ' . esc_attr($attributes['width']) . 'px;"' : '';
533
534
535 $page_url = urlencode(get_permalink() . '?hash=' . $content_id . '&unique=' . $content_hash);
536
537 $social_icons = '<div class="ep-social-share-wraper"' . $style . ' ><div class="ep-social-share share-position-' . esc_attr($share_position) . '">';
538
539
540 // Facebook
541 if ($facebook_enabled) {
542 $social_icons .= '<a href="https://www.facebook.com/sharer/sharer.php?u=' . $page_url . '" class="ep-social-icon facebook" target="_blank">
543 <svg width="64px" height="64px" fill="#000000" viewBox="0 -6 512 512" xmlns="http://www.w3.org/2000/svg">
544 <path d="M0 0h512v500H0z" fill="#475a96"/>
545 <path d="m375.72 112.55h-237.43c-8.137 0-14.73 6.594-14.73 14.73v237.43c0 8.135 6.594 14.73 14.73 14.73h127.83v-103.36h-34.781v-40.28h34.781v-29.705c0-34.473 21.055-53.244 51.807-53.244 14.73 0 27.391 1.097 31.08 1.587v36.026l-21.328 0.01c-16.725 0-19.963 7.947-19.963 19.609v25.717h39.887l-5.193 40.28h-34.693v103.36h68.012c8.135 0 14.73-6.596 14.73-14.73v-237.43c-1e-3 -8.137-6.596-14.73-14.731-14.73z" fill="#fff"/>
546 </svg>
547 </a>';
548 }
549
550 // Twitter
551 if ($twitter_enabled) {
552 $social_icons .= '<a href="https://twitter.com/intent/tweet?url=' . $page_url . '&text=' . $custom_title . '" class="ep-social-icon twitter" target="_blank">
553 <svg viewBox="0 0 24 24" aria-hidden="true" fill="#fff" class="r-4qtqp9 r-yyyyoo r-dnmrzs r-bnwqim r-lrvibr r-m6rgpd r-lrsllp r-1nao33i r-16y2uox r-8kz0gk"><g><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path></g></svg>
554 </a>';
555 }
556
557 // Pinterest
558 if ($pinterest_enabled) {
559 $social_icons .= '<a href="http://pinterest.com/pin/create/button/?url=' . $page_url . '&media=' . $custom_thumnail . '&description=' . $custom_description . '" class="ep-social-icon pinterest" target="_blank">
560
561 <svg xmlns="http://www.w3.org/2000/svg" height="800" width="1200" viewBox="-36.42015 -60.8 315.6413 364.8"><path d="M121.5 0C54.4 0 0 54.4 0 121.5 0 173 32 217 77.2 234.7c-1.1-9.6-2-24.4.4-34.9 2.2-9.5 14.2-60.4 14.2-60.4s-3.6-7.3-3.6-18c0-16.9 9.8-29.5 22-29.5 10.4 0 15.4 7.8 15.4 17.1 0 10.4-6.6 26-10.1 40.5-2.9 12.1 6.1 22 18 22 21.6 0 38.2-22.8 38.2-55.6 0-29.1-20.9-49.4-50.8-49.4-34.6 0-54.9 25.9-54.9 52.7 0 10.4 4 21.6 9 27.7 1 1.2 1.1 2.3.8 3.5-.9 3.8-3 12.1-3.4 13.8-.5 2.2-1.8 2.7-4.1 1.6-15.2-7.1-24.7-29.2-24.7-47.1 0-38.3 27.8-73.5 80.3-73.5 42.1 0 74.9 30 74.9 70.2 0 41.9-26.4 75.6-63 75.6-12.3 0-23.9-6.4-27.8-14 0 0-6.1 23.2-7.6 28.9-2.7 10.6-10.1 23.8-15.1 31.9 11.4 3.5 23.4 5.4 36 5.4 67.1 0 121.5-54.4 121.5-121.5C243 54.4 188.6 0 121.5 0z" fill="#fff"/></svg>
562
563 </a>';
564 }
565
566 // LinkedIn
567 if ($linkedin_enabled) {
568 $social_icons .= '<a href="https://www.linkedin.com/shareArticle?mini=true&url=' . $page_url . '" class="ep-social-icon linkedin" target="_blank">
569
570 <svg fill="#ffffff" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
571 viewBox="0 0 310 310" xml:space="preserve">
572 <g id="XMLID_801_">
573 <path id="XMLID_802_" d="M72.16,99.73H9.927c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5H72.16c2.762,0,5-2.238,5-5V104.73
574 C77.16,101.969,74.922,99.73,72.16,99.73z"/>
575 <path id="XMLID_803_" d="M41.066,0.341C18.422,0.341,0,18.743,0,41.362C0,63.991,18.422,82.4,41.066,82.4
576 c22.626,0,41.033-18.41,41.033-41.038C82.1,18.743,63.692,0.341,41.066,0.341z"/>
577 <path id="XMLID_804_" d="M230.454,94.761c-24.995,0-43.472,10.745-54.679,22.954V104.73c0-2.761-2.238-5-5-5h-59.599
578 c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5h62.097c2.762,0,5-2.238,5-5v-98.918c0-33.333,9.054-46.319,32.29-46.319
579 c25.306,0,27.317,20.818,27.317,48.034v97.204c0,2.762,2.238,5,5,5H305c2.762,0,5-2.238,5-5V194.995
580 C310,145.43,300.549,94.761,230.454,94.761z"/>
581 </g>
582 </svg>
583 </a>';
584 }
585
586 $social_icons .= '</div></div>';
587
588 return $social_icons;
589 }
590
591 public static function ep_get_elementor_widget_settings($page_settings = '', $id = '', $widgetType = '')
592 {
593 if (empty($page_settings)) {
594 return [];
595 }
596
597 // Handle both string and array cases for elementor data
598 if (is_string($page_settings)) {
599 $data = json_decode($page_settings, true);
600 } else {
601 // Data might already be an array in older versions
602 $data = $page_settings;
603 }
604 $element_setting = null;
605
606 Plugin::$instance->db->iterate_data($data, function ($element) use (&$element_setting, $widgetType, $id) {
607
608 if ($element['id'] == $id && $element['elType'] == 'widget' && $element['widgetType'] == $widgetType) {
609 $element_setting[] = $element['settings'];
610 }
611 });
612
613 return $element_setting;
614 }
615
616
617
618 public static function ep_get_popup_icon()
619 {
620 $svg = '<div class="ep-doc-popup-icon" ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" xml:space="preserve"><path fill="#fff" d="M5 3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-6l-2-2v8H5V5h8l-2-2H5zm9 0 2.7 2.7-7.5 7.5 1.7 1.7 7.5-7.5L21 10V3h-7z"/><path style="fill:none" d="M0 0h24v24H0z"/></svg></div>';
621
622 return $svg;
623 }
624 public static function ep_get_download_icon()
625 {
626 $svg = '<div class="ep-doc-download-icon" ><svg width="25" height="25" viewBox="0 0 0.6 0.6" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" fill-rule="evenodd" d="M.525.4A.025.025 0 0 1 .55.422v.053A.075.075 0 0 1 .479.55H.125A.075.075 0 0 1 .05.479V.425A.025.025 0 0 1 .1.422v.053A.025.025 0 0 0 .122.5h.353A.025.025 0 0 0 .5.478V.425A.025.025 0 0 1 .525.4ZM.3.05a.025.025 0 0 1 .025.025v.24L.357.283A.025.025 0 0 1 .39.281l.002.002a.025.025 0 0 1 .002.033L.392.318.317.393.316.394.314.395.311.397.308.398.305.399.301.4H.295L.292.399.289.398.287.397.285.395A.025.025 0 0 1 .283.393L.208.318A.025.025 0 0 1 .241.281l.002.002.032.032v-.24A.025.025 0 0 1 .3.05Z"/></svg></div>';
627
628 return $svg;
629 }
630
631 public static function ep_get_print_icon()
632 {
633 $svg = '<div class="ep-doc-print-icon" ><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24">
634 <path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z" fill="#fff"/>
635 </svg></div>';
636
637 return $svg;
638 }
639
640 public static function ep_get_fullscreen_icon()
641 {
642 $svg = '<div class="ep-doc-fullscreen-icon"><svg width="25" height="25" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
643 <path d="m3 15 .117.007a1 1 0 0 1 .876.876L4 16v4h4l.117.007a1 1 0 0 1 0 1.986L8 22H3l-.117-.007a1 1 0 0 1-.876-.876L2 21v-5l.007-.117a1 1 0 0 1 .876-.876L3 15Zm18 0a1 1 0 0 1 .993.883L22 16v5a1 1 0 0 1-.883.993L21 22h-5a1 1 0 0 1-.117-1.993L16 20h4v-4a1 1 0 0 1 .883-.993L21 15ZM8 2a1 1 0 0 1 .117 1.993L8 4H4v4a1 1 0 0 1-.883.993L3 9a1 1 0 0 1-.993-.883L2 8V3a1 1 0 0 1 .883-.993L3 2h5Zm13 0 .117.007a1 1 0 0 1 .876.876L22 3v5l-.007.117a1 1 0 0 1-.876.876L21 9l-.117-.007a1 1 0 0 1-.876-.876L20 8V4h-4l-.117-.007a1 1 0 0 1 0-1.986L16 2h5Z" fill="#fff"/>
644 </svg></div>';
645
646 return $svg;
647 }
648 public static function ep_get_minimize_icon()
649 {
650 $svg = '<div class="ep-doc-minimize-icon" style="display:none"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" style="enable-background:new 0 0 385.331 385.331" xml:space="preserve" width="20" height="20"><path fill="#fff" d="M13.751 8.131h5.62c0.355 0 0.619 -0.28 0.619 -0.634 0 -0.355 -0.265 -0.615 -0.619 -0.614h-4.995V1.878c0 -0.355 -0.27 -0.624 -0.624 -0.624s-0.624 0.27 -0.624 0.624v5.62c0 0.002 0.001 0.003 0.001 0.004 0 0.002 -0.001 0.003 -0.001 0.005 0 0.348 0.276 0.625 0.624 0.624zM6.244 1.259c-0.354 0 -0.614 0.265 -0.614 0.619v4.995H0.624c-0.355 0 -0.624 0.27 -0.624 0.624 0 0.355 0.27 0.624 0.624 0.624h5.62c0.002 0 0.003 -0.001 0.004 -0.001 0.002 0 0.003 0.001 0.005 0.001 0.348 0 0.624 -0.276 0.624 -0.624V1.878c0 -0.354 -0.28 -0.619 -0.634 -0.619zm0.005 10.61H0.629c-0.355 0.001 -0.619 0.28 -0.619 0.634 0 0.355 0.265 0.615 0.619 0.614h4.995v5.005c0 0.355 0.27 0.624 0.624 0.624 0.355 0 0.624 -0.27 0.624 -0.624V12.502c0 -0.002 -0.001 -0.003 -0.001 -0.004 0 -0.002 0.001 -0.003 0.001 -0.005 0 -0.348 -0.276 -0.624 -0.624 -0.624zm13.127 0H13.756c-0.002 0 -0.003 0.001 -0.004 0.001 -0.002 0 -0.003 -0.001 -0.005 -0.001 -0.348 0 -0.624 0.276 -0.624 0.624v5.62c0 0.355 0.28 0.619 0.634 0.619 0.354 0.001 0.614 -0.265 0.614 -0.619v-4.995H19.376c0.355 0 0.624 -0.27 0.624 -0.624s-0.27 -0.624 -0.624 -0.625z"/><g/><g/><g/><g/><g/><g/></svg></div>';
651
652 return $svg;
653 }
654 public static function ep_get_draw_icon()
655 {
656 $svg = '<div class="ep-doc-draw-icon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="m15 7.5 2.5 2.5m-10 10L19.25 8.25c0.69 -0.69 0.69 -1.81 0 -2.5v0c-0.69 -0.69 -1.81 -0.69 -2.5 0L5 17.5V20h2.5Zm0 0h8.379C17.05 20 18 19.05 18 17.879v0c0 -0.563 -0.224 -1.103 -0.621 -1.5L17 16M4.5 5c2 -2 5.5 -1 5.5 1 0 2.5 -6 2.5 -6 5 0 0.876 0.533 1.526 1.226 2" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></div>';
657
658 return $svg;
659 }
660
661 public static function get_insta_video_icon()
662 {
663 $svg = '<svg class="insta-video-icon" aria-label="Clip" class="x1lliihq x1n2onr6" color="#FFF" fill="#FFF" height="20" viewBox="1.111 1.111 24.444 24.447" width="20">
664 <path d="m14.248 1.111 3.304 5.558h-6.2L8.408 1.146c.229-.014.466-.024.713-.03l.379-.005Zm2.586 0h.331c3.4 0 4.964.838 6.267 2.097a6.674 6.674 0 0 1 1.773 3.133l.078.328H20.14l-3.307-5.558ZM6.093 1.53l2.74 5.139H1.382a6.678 6.678 0 0 1 4.38-5.033ZM16.91 15.79l-5.05-2.916a1.01 1.01 0 0 0-1.507.742l-.009.133v5.831a1.011 1.011 0 0 0 1.394.933l.121-.059 5.05-2.916a1.01 1.01 0 0 0 .111-1.674l-.111-.076-5.05-2.916ZM1.132 8.891h24.404l.017.4.003.21v7.666c0 3.401-.839 4.966-2.098 6.267-1.279 1.238-2.778 2.062-5.922 2.121l-.371.003H9.501c-3.4 0-4.963-.839-6.267-2.099-1.238-1.278-2.06-2.776-2.12-5.922l-.003-.37V9.501l.003-.21Z" fill-rule="evenodd" /></svg>';
665
666 return $svg;
667 }
668
669 public static function get_insta_image_carousel_icon()
670 {
671 $svg = '<svg aria-label="Carousel" class="x1lliihq x1n2onr6" color="#FFF" fill="#FFF" height="25" viewBox="0 0 43.636 43.636" width="25">
672 <path d="M31.636 27V10a4.695 4.695 0 0 0-4.727-4.727H10A4.695 4.695 0 0 0 5.273 10v17A4.695 4.695 0 0 0 10 31.727h17c2.545-.091 4.636-2.182 4.636-4.727zm4-13.364v14.636c0 4.091-3.364 7.455-7.455 7.455H13.545c-.545 0-.818.636-.455 1 .909 1 2.182 1.636 3.727 1.636h12.182a9.35 9.35 0 0 0 9.364-9.364V16.818a5.076 5.076 0 0 0-1.636-3.727c-.455-.364-1.091 0-1.091.545z" /></svg>';
673
674 return $svg;
675 }
676
677 public static function get_insta_image_icon()
678 {
679 $svg = '<svg width="22" height="22" viewBox="0 0 0.6 0.6" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M.175.05A.125.125 0 0 0 .05.175v.25A.125.125 0 0 0 .175.55h.25A.125.125 0 0 0 .55.425v-.25A.125.125 0 0 0 .425.05h-.25ZM.2.225a.025.025 0 1 1 .05 0 .025.025 0 0 1-.05 0ZM.225.15a.075.075 0 1 0 0 .15.075.075 0 0 0 0-.15Zm.138.205A.025.025 0 0 1 .398.351l.048.042A.025.025 0 1 0 .479.355L.43.312a.075.075 0 0 0-.107.011l-.04.05a.024.024 0 0 1-.032.005.074.074 0 0 0-.099.015L.118.432a.025.025 0 0 0 .038.033l.035-.04A.024.024 0 0 1 .223.42.074.074 0 0 0 .322.405l.04-.05Z" fill="#fff"/></svg>';
680
681 return $svg;
682 }
683
684 public static function get_insta_like_icon()
685 {
686 $svg = '<svg version="1.1" id="Uploaded to svgrepo.com" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 0.8 0.8" xml:space="preserve"><path d="M.225.25C.225.264.214.275.2.275S.175.264.175.25.186.225.2.225.225.236.225.25zM.75.3C.75.453.589.582.485.65a1.06 1.06 0 0 1-.073.044.025.025 0 0 1-.024 0A1.049 1.049 0 0 1 .315.65C.211.582.05.453.05.3a.2.2 0 0 1 .2-.2.199.199 0 0 1 .15.068A.199.199 0 0 1 .55.1a.2.2 0 0 1 .2.2zM.25.25a.05.05 0 1 0-.1 0 .05.05 0 0 0 .1 0z" style="fill:#fff"/></svg>';
687
688 return $svg;
689 }
690 public static function get_insta_comment_icon()
691 {
692 $svg = '<svg fill="#fff" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 2.5 2.5" xml:space="preserve"><path d="M2.374.446a.063.063 0 0 0-.061-.057H.991a.063.063 0 0 0-.063.057H.927v.328h.559c.029 0 .053.022.056.051h.001v.731h.275l.162.162a.063.063 0 0 0 .116-.035v-.127h.217a.063.063 0 0 0 .06-.051h.002V.446h-.001z"/><path d="M1.361.899H.18A.056.056 0 0 0 .125.95v.946h.001a.057.057 0 0 0 .054.045h.194v.113a.057.057 0 0 0 .104.032l.145-.145h.738c.027 0 .05-.02.056-.045h.001V.95h-.001a.056.056 0 0 0-.056-.051z"/></svg>';
693
694 return $svg;
695 }
696 public static function get_instagram_icon()
697 {
698 $svg = '<svg version="1.1" id="Icons" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" xml:space="preserve" width="1285" height="400"><style>.st0{fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}</style><path class="st0" d="M14.375 19.375h-8.75c-2.75 0-5-2.25-5-5v-8.75c0-2.75 2.25-5 5-5h8.75c2.75 0 5 2.25 5 5v8.75c0 2.75-2.25 5-5 5z"/><path class="st0" d="M14.375 10A4.375 4.375 0 0 1 10 14.375 4.375 4.375 0 0 1 5.625 10a4.375 4.375 0 0 1 8.75 0zm1.25-5.625A.625.625 0 0 1 15 5a.625.625 0 0 1-.625-.625.625.625 0 0 1 1.25 0z"/></svg>';
699
700 return $svg;
701 }
702
703 public static function get_google_presentation_url($embedded_url)
704 {
705 $parsed_url = parse_url($embedded_url);
706 $base_url = $parsed_url['scheme'] . '://' . $parsed_url['host'] . $parsed_url['path'];
707 $base_url = strtok($base_url, '?');
708 $base_url = rtrim($base_url, '/');
709 return $base_url;
710 }
711
712 public static function check_media_format($url)
713 {
714 // Strip query/hash so signed streaming URLs (Mux, CloudFront) match.
715 $path = preg_replace('/[?#].*$/', '', (string) $url);
716 $pattern1 = '/\.(mp4|mov|avi|wmv|flv|mkv|webm|mpeg|mpg|m3u8|mpd)$/i';
717 $pattern2 = '/\.(mp3|wav|ogg|aac)$/i';
718
719 $isVideo = preg_match($pattern1, $path);
720 $isAudio = preg_match($pattern2, $path);
721
722 $is_self_hosted = false;
723 $format = '';
724
725 if (!empty($isVideo) || !empty($isAudio)) {
726 $is_self_hosted = true;
727 if (!empty($isVideo)) {
728 $format = 'video';
729 } else if (!empty($isAudio)) {
730 $format = 'audio';
731 }
732 }
733
734 if (!$is_self_hosted) {
735 return [
736 'selhosted' => false,
737 ];
738 }
739
740 return [
741 'selhosted' => true,
742 'format' => $format,
743 ];
744 }
745
746 // Ajax Methods get instagram feed data
747 public function loadmore_data_handler()
748 {
749 $connected_account_type = isset($_POST['connected_account_type']) ? sanitize_text_field($_POST['connected_account_type']) : 'personal';
750 $hashtag_id = isset($_POST['hashtag_id']) ? sanitize_text_field($_POST['hashtag_id']) : '';
751 $feed_type = isset($_POST['feed_type']) ? sanitize_text_field($_POST['feed_type']) : 'user_aacount_type';
752 $user_id = isset($_POST['user_id']) ? sanitize_text_field($_POST['user_id']) : '';
753 $loadmore_key = isset($_POST['loadmore_key']) ? sanitize_text_field($_POST['loadmore_key']) : '';
754 $nonce = isset($_POST['_nonce']) ? sanitize_text_field($_POST['_nonce']) : '';
755 $params = isset($_POST['params']) ? sanitize_text_field($_POST['params']) : '';
756 // $params = json_decode($params, true);
757 $params = stripslashes($params); // Remove extra backslashes
758 $params = json_decode($params, true);
759
760 // Verify nonce
761 if (!wp_verify_nonce($nonce, 'ep_nonce')) {
762 wp_send_json_error('Invalid nonce');
763 wp_die(); // Terminate script execution if nonce is invalid
764 }
765
766 $feeds_data = get_option('ep_instagram_feed_data');
767 $user_data = $feeds_data[$user_id]['feed_userinfo'];
768
769 if ($feed_type == 'hashtag_type') {
770 $feeds_data = get_option('ep_instagram_hashtag_feed');
771 }
772
773
774 $profile_picture_url = isset($user_data['profile_picture_url']) ? $user_data['profile_picture_url'] : '';
775
776 if ($feed_type === 'user_account_type' && isset($feeds_data[$loadmore_key]['feed_posts'])) {
777 $feed_posts = $feeds_data[$loadmore_key]['feed_posts'];
778 } else if ($feed_type === 'hashtag_type' && isset($feeds_data[$loadmore_key])) {
779 $feed_posts = $feeds_data[$loadmore_key];
780 } else {
781 $feed_posts = ['error'];
782 }
783
784
785 if (is_array($feed_posts) && count($feed_posts) > 0) {
786 $loaded_posts = isset($_POST['loaded_posts']) ? intval($_POST['loaded_posts']) : 0;
787 $posts_per_page = isset($_POST['posts_per_page']) ? intval($_POST['posts_per_page']) : 0;
788
789 $post_index = $loaded_posts + 1;
790 $start_index = $loaded_posts;
791
792 $next_posts = array_slice($feed_posts, $start_index, $posts_per_page);
793
794 ob_start();
795
796 if (is_array($next_posts) && count($next_posts) > 0) :
797 foreach ($next_posts as $post) :
798 $caption = !empty($post['caption']) ? $post['caption'] : '';
799 $media_type = !empty($post['media_type']) ? $post['media_type'] : '';
800 $media_url = !empty($post['media_url']) ? $post['media_url'] : '';
801 $permalink = !empty($post['permalink']) ? $post['permalink'] : '';
802 $timestamp = !empty($post['timestamp']) ? $post['timestamp'] : '';
803 $username = !empty($post['username']) ? $post['username'] : '';
804 $like_count = !empty($post['like_count']) ? $post['like_count'] : 0;
805 $comments_count = !empty($post['comments_count']) ? $post['comments_count'] : 0;
806
807 $post['profile_picture_url'] = $profile_picture_url;
808 $post['show_likes_count'] = isset($params['show_likes_count']) ? $params['show_likes_count'] : false;
809 $post['show_comments_count'] = isset($params['show_comments_count']) ? $params['show_comments_count'] : false;
810 $post['popup_follow_button'] = isset($params['popup_follow_button']) ? $params['popup_follow_button'] : true;
811 $post['popup_follow_button_text'] = isset($params['popup_follow_button_text']) ? $params['popup_follow_button_text'] : 'Follow';
812 ?>
813
814 <div class="insta-gallery-item cg-carousel__slide js-carousel__slide" data-insta-postid="<?php echo esc_attr($post['id']) ?>" data-postindex="<?php echo esc_attr($post_index); ?>" data-postdata="<?php echo htmlspecialchars(json_encode($post), ENT_QUOTES, 'UTF-8'); ?>" data-media-type="<?php echo esc_attr($media_type); ?>">
815 <?php
816
817 if (!empty($hashtag_id) && $media_type == 'CAROUSEL_ALBUM') {
818 if (isset($post['children']['data'][0]['media_url'])) {
819 $hashtag_media_url = $post['children']['data'][0]['media_url'];
820 $hashtag_media_type = $post['children']['data'][0]['media_type'];
821
822 if ($hashtag_media_type == 'VIDEO') {
823 echo '<video class="insta-gallery-image" src="' . esc_url($hashtag_media_url) . '"></video>';
824 } else {
825 echo ' <img class="insta-gallery-image" src="' . esc_url($hashtag_media_url) . '" alt="' . esc_attr('image') . '">';
826 }
827 }
828 } else {
829 if ($media_type == 'VIDEO') {
830 echo '<video class="insta-gallery-image" src="' . esc_url($media_url) . '"></video>';
831 } else {
832 echo ' <img class="insta-gallery-image" src="' . esc_url($media_url) . '" alt="' . esc_attr('image') . '">';
833 }
834 }
835 ?>
836
837 <div class="insta-gallery-item-type">
838 <div class="insta-gallery-item-type-icon">
839 <?php
840 if ($media_type == 'VIDEO') {
841 echo Helper::get_insta_video_icon();
842 } else if ($media_type == 'CAROUSEL_ALBUM') {
843 echo Helper::get_insta_image_carousel_icon();
844 } else {
845 echo Helper::get_insta_image_icon();
846 }
847 ?>
848 </div>
849 </div>
850 <div class="insta-gallery-item-info">
851 <?php if (apply_filters('embedpress/is_allow_rander', false)): ?>
852 <div class="insta-item-reaction-count">
853 <div class="insta-gallery-item-likes">
854 <?php echo Helper::get_insta_like_icon();
855 echo esc_html($like_count); ?>
856 </div>
857 <div class="insta-gallery-item-comments">
858 <?php echo Helper::get_insta_comment_icon();
859 echo esc_html($comments_count); ?>
860 </div>
861 </div>
862 <?php else : ?>
863 <div class="insta-gallery-item-permalink">
864 <?php echo Helper::get_instagram_icon(); ?>
865 </div>
866 <?php endif; ?>
867 </div>
868 </div>
869
870 <?php $post_index++;
871 endforeach;
872 endif;
873
874 $feed_item = ob_get_clean();
875
876 $next_start_index = $start_index + count($next_posts);
877
878 wp_send_json(array(
879 'html' => $feed_item,
880 'next_post_index' => $next_start_index,
881 'total_feed_posts' => count($feed_posts)
882 ));
883 } else {
884 wp_send_json('');
885 }
886 }
887
888 public static function getCalendlyUuid($url)
889 {
890 $pattern = '/\/([0-9a-fA-F-]+)$/';
891 if (preg_match($pattern, $url, $matches)) {
892 $uuid = $matches[1];
893 return $uuid;
894 }
895 return '';
896 }
897
898 public static function getCalendlyUserInfo($access_token)
899 {
900 $transient_name = 'calendly_user_info_' . $access_token;
901 $user_info = get_transient($transient_name);
902 if (false === $user_info) {
903 $user_endpoint = 'https://api.calendly.com/users/me';
904 $headers = array(
905 'Authorization' => "Bearer $access_token",
906 'Content-Type' => 'application/json',
907 );
908 $args = array(
909 'headers' => $headers,
910 );
911 $response = wp_remote_get($user_endpoint, $args);
912 if (!is_wp_error($response) && 200 === wp_remote_retrieve_response_code($response)) {
913 $user_info = wp_remote_retrieve_body($response);
914 set_transient($transient_name, $user_info, 3600);
915 } else {
916 return false;
917 }
918 }
919
920 return $user_info;
921 }
922
923
924
925 public static function getCalaendlyEventTypes($user_uri, $access_token)
926 {
927 // Attempt to retrieve the data from the transient
928 $events_list = get_transient('calendly_events_list_' . md5($access_token));
929
930 if (false === $events_list) {
931 // If the data is not in the transient, fetch it from the API
932 $events_endpoint = "https://api.calendly.com/event_types?user=$user_uri";
933
934 $headers = array(
935 'Authorization' => "Bearer $access_token",
936 'Content-Type' => 'application/json',
937 );
938
939 $args = array(
940 'headers' => $headers,
941 );
942
943 $response = wp_remote_get($events_endpoint, $args);
944
945 if (!is_wp_error($response)) {
946 $body = wp_remote_retrieve_body($response);
947 $events_list = json_decode($body, true);
948
949 // Store the data in a transient for a specified time (e.g., 1 hour)
950 set_transient('calendly_events_list', $events_list, HOUR_IN_SECONDS);
951
952 return $events_list;
953 }
954 }
955
956 return $events_list;
957 }
958
959 public static function getListEventInvitee($uuid, $access_token)
960 {
961 // Attempt to retrieve the data from the transient
962 $invitee_list = get_transient('calendly_invitee_list_' . md5($access_token));
963
964 if (false === $invitee_list) {
965 // If the data is not in the transient, fetch it from the API
966 $events_endpoint = "https://api.calendly.com/scheduled_events/$uuid/invitees";
967
968 $headers = array(
969 'Authorization' => "Bearer $access_token",
970 'Content-Type' => 'application/json',
971 );
972
973 $args = array(
974 'headers' => $headers,
975 );
976
977 $response = wp_remote_get($events_endpoint, $args);
978
979 if (!is_wp_error($response)) {
980 $body = wp_remote_retrieve_body($response);
981 $invitee_list = json_decode($body, true);
982
983 // Store the data in a transient for a specified time (e.g., 1 hour)
984 set_transient('calendly_invitee_list', $invitee_list, HOUR_IN_SECONDS);
985
986 return $invitee_list;
987 }
988 }
989
990 return $invitee_list;
991 }
992
993 public static function getCalaendlyScheduledEvents($user_uri, $access_token)
994 {
995 // Attempt to retrieve the data from the transient
996 $events_list = get_transient('calendly_events_list_' . md5($access_token));
997
998 if (false === $events_list) {
999 // If the data is not in the transient, fetch it from the API
1000 $events_endpoint = "https://api.calendly.com/scheduled_events?user=$user_uri";
1001
1002 $headers = array(
1003 'Authorization' => "Bearer $access_token",
1004 'Content-Type' => 'application/json',
1005 );
1006
1007 $args = array(
1008 'headers' => $headers,
1009 );
1010
1011 $response = wp_remote_get($events_endpoint, $args);
1012
1013 if (!is_wp_error($response)) {
1014 $body = wp_remote_retrieve_body($response);
1015 $events_list = json_decode($body, true);
1016
1017 // Store the data in a transient for a specified time (e.g., 1 hour)
1018 set_transient('calendly_events_list', $events_list, HOUR_IN_SECONDS);
1019
1020 return $events_list;
1021 }
1022 }
1023
1024 return $events_list;
1025 }
1026
1027
1028 public static function parseDuration($durationString)
1029 {
1030 list($minutes, $seconds) = explode(':', $durationString);
1031 return intval($minutes) * 60 + intval($seconds);
1032 }
1033
1034
1035
1036
1037 public static function is_pro_active()
1038 {
1039 if (defined('EMBEDPRESS_SL_ITEM_SLUG')) {
1040 return true;
1041 }
1042 return false;
1043 }
1044
1045 /**
1046 * Check if pro features should be enabled based on license status
1047 *
1048 * @return bool True if pro features should be enabled, false otherwise
1049 */
1050 public static function is_pro_features_enabled()
1051 {
1052 // First check if pro plugin is active
1053 if (!self::is_pro_active()) {
1054 return false;
1055 }
1056
1057 // Get license status
1058 $license_status = get_option('embedpress_pro_software__license_status', '');
1059
1060 // Pro features are enabled only if license is valid
1061 return $license_status === 'valid';
1062 }
1063
1064 /**
1065 * Get detailed license information
1066 *
1067 * @return array License information including status, key, and data
1068 */
1069 public static function get_license_info()
1070 {
1071 $is_pro_active = self::is_pro_active();
1072 $license_status = '';
1073 $license_key = '';
1074 $license_data = [];
1075 $is_features_enabled = false;
1076
1077 if ($is_pro_active) {
1078 $license_status = get_option('embedpress_pro_software__license_status', '');
1079 $license_data_raw = get_transient('embedpress_pro_software__license_data');
1080
1081 if ($license_data_raw) {
1082 $license_data = json_decode(json_encode($license_data_raw), true);
1083 $license_key = isset($license_data['license_key']) ? $license_data['license_key'] : '';
1084 }
1085
1086 $is_features_enabled = ($license_status === 'valid');
1087 }
1088
1089 return [
1090 'is_pro_active' => $is_pro_active,
1091 'license_status' => $license_status,
1092 'license_key' => $license_key,
1093 'license_data' => $license_data,
1094 'is_features_enabled' => $is_features_enabled,
1095 'status_message' => self::get_license_status_message($is_pro_active, $license_status)
1096 ];
1097 }
1098
1099 /**
1100 * Display license warning notice for pro features
1101 *
1102 * @param string $context Context where the notice is displayed (e.g., 'analytics', 'branding')
1103 * @return string HTML for the license warning notice
1104 */
1105 public static function get_pro_feature_notice($context = '')
1106 {
1107 $license_info = self::get_license_info();
1108
1109 if (!$license_info['is_pro_active']) {
1110 return '<div class="embedpress-pro-notice embedpress-notice-warning">
1111 <p><strong>' . __('EmbedPress Pro Required', 'embedpress') . '</strong></p>
1112 <p>' . __('This feature requires EmbedPress Pro. Please install and activate EmbedPress Pro to access this feature.', 'embedpress') . '</p>
1113 </div>';
1114 }
1115
1116 if (!$license_info['is_features_enabled']) {
1117 $message = $license_info['status_message'];
1118 $action_text = '';
1119 $action_link = admin_url('admin.php?page=embedpress&page_type=license');
1120
1121 switch ($license_info['license_status']) {
1122 case 'expired':
1123 $action_text = __('Renew License', 'embedpress');
1124 break;
1125 case 'invalid':
1126 case 'site_inactive':
1127 case 'disabled':
1128 case 'revoked':
1129 $action_text = __('Activate License', 'embedpress');
1130 break;
1131 default:
1132 $action_text = __('Activate License', 'embedpress');
1133 break;
1134 }
1135
1136 return '<div class="embedpress-pro-notice embedpress-notice-error">
1137 <p><strong>' . __('Pro Features Disabled', 'embedpress') . '</strong></p>
1138 <p>' . esc_html($message) . '</p>
1139 <p><a href="' . esc_url($action_link) . '" class="button button-primary">' . esc_html($action_text) . '</a></p>
1140 </div>';
1141 }
1142
1143 return '';
1144 }
1145
1146 /**
1147 * Initialize license checking hooks
1148 */
1149 public static function init_license_hooks()
1150 {
1151 // Add filter to disable pro features when license is not valid
1152 add_filter('embedpress_pro_features_enabled', [__CLASS__, 'is_pro_features_enabled']);
1153
1154 // Add action to show license notices in admin
1155 add_action('admin_notices', [__CLASS__, 'show_license_admin_notices']);
1156
1157 // Add styles for license notices
1158 add_action('admin_head', [__CLASS__, 'add_license_notice_styles']);
1159 }
1160
1161 /**
1162 * Show license admin notices
1163 */
1164 public static function show_license_admin_notices()
1165 {
1166 // Only show on EmbedPress admin pages
1167 if (!isset($_GET['page']) || $_GET['page'] !== 'embedpress') {
1168 return;
1169 }
1170
1171 $license_info = self::get_license_info();
1172
1173 if ($license_info['is_pro_active'] && !$license_info['is_features_enabled']) {
1174 $message = $license_info['status_message'];
1175 $action_link = admin_url('admin.php?page=embedpress&page_type=license');
1176 $action_text = $license_info['license_status'] === 'expired' ? __('Renew License', 'embedpress') : __('Activate License', 'embedpress');
1177
1178 echo '<div class="notice notice-warning is-dismissible">
1179 <p><strong>' . __('EmbedPress Pro Features Disabled', 'embedpress') . '</strong></p>
1180 <p>' . esc_html($message) . '</p>
1181 <p><a href="' . esc_url($action_link) . '" class="button button-primary">' . esc_html($action_text) . '</a></p>
1182 </div>';
1183 }
1184 }
1185
1186 /**
1187 * Add CSS styles for license notices
1188 */
1189 public static function add_license_notice_styles()
1190 {
1191 echo '<style>
1192 .embedpress-pro-notice {
1193 padding: 15px;
1194 margin: 15px 0;
1195 border-left: 4px solid #dc3545;
1196 background: #fff;
1197 box-shadow: 0 1px 1px rgba(0,0,0,.04);
1198 }
1199 .embedpress-pro-notice.embedpress-notice-warning {
1200 border-left-color: #ffb900;
1201 }
1202 .embedpress-pro-notice.embedpress-notice-error {
1203 border-left-color: #dc3545;
1204 }
1205 .embedpress-pro-notice p {
1206 margin: 0.5em 0;
1207 }
1208 .embedpress-pro-notice strong {
1209 color: #23282d;
1210 }
1211 .embedpress-text-error {
1212 color: #dc3545 !important;
1213 }
1214 .embedpress-text-warning {
1215 color: #ffb900 !important;
1216 }
1217 </style>';
1218 }
1219
1220 /**
1221 * Get user-friendly license status message
1222 *
1223 * @param bool $is_pro_active Whether pro plugin is active
1224 * @param string $license_status Current license status
1225 * @return string User-friendly status message
1226 */
1227 public static function get_license_status_message($is_pro_active, $license_status)
1228 {
1229 if (!$is_pro_active) {
1230 return __('EmbedPress Pro is not installed or activated.', 'embedpress');
1231 }
1232
1233 switch ($license_status) {
1234 case 'valid':
1235 return __('Your license is active and valid.', 'embedpress');
1236 case 'expired':
1237 return __('Your license has expired. Please renew to continue receiving updates and support.', 'embedpress');
1238 case 'invalid':
1239 case 'site_inactive':
1240 return __('Your license is not active for this URL. Please activate your license.', 'embedpress');
1241 case 'disabled':
1242 case 'revoked':
1243 return __('Your license key has been disabled or revoked.', 'embedpress');
1244 case 'missing':
1245 return __('License key is missing. Please enter your license key.', 'embedpress');
1246 case 'http_error':
1247 return __('Unable to verify license due to connection issues. Please try again later.', 'embedpress');
1248 case '':
1249 case false:
1250 default:
1251 return __('Please activate your license key to enable EmbedPress Pro features.', 'embedpress');
1252 }
1253 }
1254
1255
1256 public static function getInstagramUserInfo($accessToken, $accountType, $userId, $is_sync = false)
1257 {
1258 if ($is_sync) {
1259 // If $is_sync is true, don't use transient
1260 $use_transient = false;
1261 } else {
1262 // If $is_sync is false, use transient
1263 $transient_key = 'instagram_user_info_' . $userId;
1264 $use_transient = true;
1265 }
1266
1267 if ($use_transient && false !== ($userInfo = get_transient($transient_key))) {
1268 // If transient exists, return cached user info
1269 return $userInfo;
1270 }
1271
1272 if (strtolower($accountType) === 'personal') {
1273 $api_url = 'https://graph.instagram.com/v24.0/me?fields=biography,id,username,website,followers_count,media_count,profile_picture_url,name&access_token=' . $accessToken;
1274 } else {
1275 $api_url = 'https://graph.facebook.com/' . $userId . '?fields=biography,id,username,website,followers_count,media_count,profile_picture_url,name&access_token=' . $accessToken;
1276 }
1277
1278 $connected_account_type = $accountType;
1279
1280 $userInfoResponse = wp_remote_get($api_url);
1281
1282 if (is_wp_error($userInfoResponse)) {
1283 echo 'Error: Unable to retrieve Instagram user information.';
1284 } else {
1285 $userInfoBody = wp_remote_retrieve_body($userInfoResponse);
1286 $userInfo = json_decode($userInfoBody, true);
1287
1288 $userInfo['connected_account_type'] = $connected_account_type;
1289 $userInfo['access_token'] = $accessToken;
1290
1291
1292 if (!isset($userInfo['profile_picture_url'])) {
1293 $userInfo['profile_picture_url'] = '';
1294 }
1295
1296 // If not using transient, cache the user info for an hour
1297 if ($use_transient) {
1298 set_transient($transient_key, $userInfo, HOUR_IN_SECONDS);
1299 }
1300
1301 return $userInfo;
1302 }
1303 }
1304
1305
1306 // Get Instagram posts, videos, reels
1307 public static function getInstagramPosts($access_token, $account_type, $userId, $limit = 100, $is_sync = false)
1308 {
1309 if ($is_sync) {
1310 // If $is_sync is true, don't use transient
1311 $use_transient = false;
1312 } else {
1313 // If $is_sync is false, use transient
1314 $transient_key = 'instagram_posts_' . $userId;
1315 $use_transient = true;
1316 }
1317
1318 if ($use_transient && false !== ($posts = get_transient($transient_key))) {
1319 // If transient exists, return cached posts
1320 return $posts;
1321 }
1322
1323 if (strtolower($account_type) === 'personal') {
1324 $api_url = 'https://graph.instagram.com/v24.0/me/media?fields=id,caption,media_type,media_url,children{media_url,id,media_type},permalink,timestamp,username,thumbnail_url,comments_count,like_count&limit=' . $limit . '&access_token=' . $access_token;
1325 } else {
1326 $api_url = 'https://graph.facebook.com/v17.0/' . $userId . '/media?fields=media_url,media_product_type,thumbnail_url,caption,id,media_type,timestamp,username,comments_count,like_count,permalink,children%7Bmedia_url,id,media_type,timestamp,permalink,thumbnail_url%7D&limit=' . $limit . '&access_token=' . $access_token;
1327 }
1328
1329 $postsResponse = wp_remote_get($api_url);
1330
1331 if (is_wp_error($postsResponse)) {
1332 echo 'Error: Unable to retrieve Instagram posts.';
1333 } else {
1334 $postsBody = wp_remote_retrieve_body($postsResponse);
1335 $posts = json_decode($postsBody, true);
1336
1337 if (empty($posts['data'])) {
1338 return 'Please add Instagram Access Token';
1339 }
1340
1341 // If not using transient, cache the posts for an hour
1342 if ($use_transient) {
1343 set_transient($transient_key, $posts['data'], HOUR_IN_SECONDS);
1344 }
1345
1346 return $posts['data'];
1347 }
1348 }
1349
1350 public static function get_enable_settings_data_for_scripts($settings)
1351 {
1352 $settings_data = [
1353 'enabled_ads' => isset($settings['adManager']) && $settings['adManager'] === 'yes' ? 'yes' : '',
1354
1355 'enabled_custom_player' => isset($settings['emberpress_custom_player']) && $settings['emberpress_custom_player'] === 'yes' ? 'yes' : '',
1356
1357 'enabled_instafeed' => isset($settings['embedpress_pro_embeded_source']) && $settings['embedpress_pro_embeded_source'] === 'instafeed' ? 'yes' : '',
1358
1359 'enabled_docs_custom_viewer' => isset($settings['embedpress_document_viewer']) && $settings['embedpress_document_viewer'] === 'custom' ? 'yes' : '',
1360 ];
1361
1362 update_option('enabled_elementor_scripts', $settings_data);
1363 }
1364
1365 public static function get_options_value($key)
1366 {
1367 $g_settings = get_option(EMBEDPRESS_PLG_NAME);
1368
1369 if (isset($g_settings['enableEmbedResizeWidth']) && $g_settings['enableEmbedResizeWidth'] == 1) {
1370 $g_settings['enableEmbedResizeWidth'] = 600;
1371 update_option(EMBEDPRESS_PLG_NAME, $g_settings);
1372 }
1373 if (isset($g_settings['enableEmbedResizeHeight']) && $g_settings['enableEmbedResizeHeight'] == 1) {
1374 $g_settings['enableEmbedResizeHeight'] = 600;
1375 update_option(EMBEDPRESS_PLG_NAME, $g_settings);
1376 }
1377
1378 if (isset($g_settings[$key])) {
1379 return $g_settings[$key];
1380 }
1381
1382 return '';
1383 }
1384
1385
1386
1387 public static function get_branding_value($key, $provider)
1388 {
1389 $settings = get_option(EMBEDPRESS_PLG_NAME . ':' . $provider, []);
1390
1391 // Check if provider has custom branding enabled and the specific key set
1392 if (isset($settings['branding']) && $settings['branding'] === 'yes') {
1393 // If provider has custom logo, use it
1394 if (isset($settings[$key]) && !empty($settings[$key])) {
1395 return $settings[$key];
1396 }
1397
1398 // If branding is enabled but no custom logo, use global brand as fallback
1399 if ($key === 'logo_url') {
1400 $global_logo = self::get_global_brand_logo_url();
1401 if (!empty($global_logo)) {
1402 return $global_logo;
1403 }
1404 }
1405 }
1406
1407 return '';
1408 }
1409
1410 /**
1411 * Get global brand logo URL
1412 *
1413 * @return string
1414 */
1415 public static function get_global_brand_logo_url()
1416 {
1417 $global_brand_settings = get_option(EMBEDPRESS_PLG_NAME . ':global_brand', []);
1418 return isset($global_brand_settings['logo_url']) ? $global_brand_settings['logo_url'] : '';
1419 }
1420
1421 /**
1422 * Get global brand logo ID
1423 *
1424 * @return int
1425 */
1426 public static function get_global_brand_logo_id()
1427 {
1428 $global_brand_settings = get_option(EMBEDPRESS_PLG_NAME . ':global_brand', []);
1429 return isset($global_brand_settings['logo_id']) ? intval($global_brand_settings['logo_id']) : 0;
1430 }
1431
1432
1433 public static function format_number($number)
1434 {
1435 if ($number >= 1000000000) {
1436 return number_format($number / 1000000000, 1) . 'b';
1437 } elseif ($number >= 1000000) {
1438 return number_format($number / 1000000, 1) . 'm';
1439 } elseif ($number >= 1000) {
1440 return number_format($number / 1000, 1) . 'k';
1441 } else {
1442 return $number;
1443 }
1444 }
1445
1446 public static function get_id($item)
1447 {
1448 $vid = isset($item->snippet->resourceId->videoId) ? $item->snippet->resourceId->videoId : null;
1449 $vid = $vid ? $vid : (isset($item->id->videoId) ? $item->id->videoId : null);
1450 $vid = $vid ? $vid : (isset($item->id) ? $item->id : null);
1451 return $vid;
1452 }
1453
1454 public static function clean_api_error($raw_message)
1455 {
1456 return htmlspecialchars(strip_tags(preg_replace('@&key=[^& ]+@i', '&key=*******', $raw_message)));
1457 }
1458
1459 public static function clean_api_error_html($raw_message)
1460 {
1461 $clean_html = '';
1462 if ((defined('REST_REQUEST') && REST_REQUEST) || current_user_can('manage_options')) {
1463 $clean_html = '<div>' . __('EmbedPress: ', 'embedpress') . self::clean_api_error($raw_message) . '</div>';
1464 }
1465 return $clean_html;
1466 }
1467
1468 public static function get_thumbnail_url($item, $quality, $privacyStatus)
1469 {
1470 $url = "";
1471 if ($privacyStatus == 'private') {
1472 $url = EMBEDPRESS_URL_ASSETS . 'images/youtube/private.png';
1473 } elseif (isset($item->snippet->thumbnails->{$quality}->url)) {
1474 $url = $item->snippet->thumbnails->{$quality}->url;
1475 } elseif (isset($item->snippet->thumbnails->medium->url)) {
1476 $url = $item->snippet->thumbnails->medium->url;
1477 } elseif (isset($item->snippet->thumbnails->default->url)) {
1478 $url = $item->snippet->thumbnails->default->url;
1479 } elseif (isset($item->snippet->thumbnails->high->url)) {
1480 $url = $item->snippet->thumbnails->high->url;
1481 } else {
1482 $url = EMBEDPRESS_URL_ASSETS . 'images/youtube/deleted-video-thumb.png';
1483 }
1484 return $url;
1485 }
1486
1487 public static function compare_vid_date($a, $b)
1488 {
1489 $dateA = strtotime($a->snippet->publishedAt);
1490 $dateB = strtotime($b->snippet->publishedAt);
1491
1492 // Sort in descending order (newest first)
1493 return $dateB - $dateA;
1494 }
1495
1496
1497 public static function get_youtube_video_data($api_key, $video_id)
1498 {
1499 // Set a unique transient name based on the video ID
1500 $transient_name = 'youtube_video_data_' . $video_id;
1501
1502 // Try to get data from the transient cache
1503 $video_data = get_transient($transient_name);
1504
1505 // If no cached data, fetch from the API
1506 if ($video_data === false) {
1507 // YouTube Data API URL
1508 $url = "https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id={$video_id}&key={$api_key}";
1509
1510 // Fetch the data from the API
1511 $response = wp_remote_get($url);
1512
1513 if (is_wp_error($response)) {
1514 return false; // Return false if there is an error
1515 }
1516
1517 $body = wp_remote_retrieve_body($response);
1518 $video_data = json_decode($body, true);
1519
1520 if (isset($video_data['items'][0])) {
1521 $video_data = $video_data['items'][0];
1522
1523 // Cache the data in a transient for 12 hours
1524 set_transient($transient_name, $video_data, 24 * HOUR_IN_SECONDS);
1525 } else {
1526 return false; // Return false if no data found
1527 }
1528 }
1529
1530 return $video_data;
1531 }
1532
1533 public static function trimTitle($title, $wordCount)
1534 {
1535 $words = explode(' ', $title);
1536
1537 if (count($words) <= $wordCount) {
1538 return $title; // No trimming needed
1539 }
1540
1541 $trimmedWords = array_slice($words, 0, $wordCount);
1542
1543 return implode(' ', $trimmedWords) . ' ...';
1544 }
1545
1546 public static function timeAgo($datetime)
1547 {
1548 $now = new \DateTime();
1549 $date = new \DateTime($datetime);
1550 $interval = $now->diff($date);
1551
1552 if ($interval->y > 0) {
1553 return $interval->y . ' year' . ($interval->y > 1 ? 's' : '') . ' ago';
1554 } elseif ($interval->m > 0) {
1555 return $interval->m . ' month' . ($interval->m > 1 ? 's' : '') . ' ago';
1556 } elseif ($interval->d > 0) {
1557 return $interval->d . ' day' . ($interval->d > 1 ? 's' : '') . ' ago';
1558 } elseif ($interval->h > 0) {
1559 return $interval->h . ' hour' . ($interval->h > 1 ? 's' : '') . ' ago';
1560 } elseif ($interval->i > 0) {
1561 return $interval->i . ' minute' . ($interval->i > 1 ? 's' : '') . ' ago';
1562 } else {
1563 return 'just now';
1564 }
1565 }
1566
1567 public static function removeQuote($attributes)
1568 {
1569 $parsedAttributes = [];
1570
1571 $regex = '/^on.*/i';
1572
1573 foreach ($attributes as $key => $value) {
1574 if (is_string($value)) {
1575 $cleanValue = str_replace(['"', "'"], '', $value);
1576 } else {
1577 $cleanValue = $value;
1578 }
1579
1580 if (!preg_match($regex, $key)) {
1581 $parsedAttributes[$key] = $cleanValue;
1582 }
1583 }
1584
1585 return $parsedAttributes;
1586 }
1587
1588 public static function getBooleanParam($param, $default = false)
1589 {
1590 if (in_array($param, [true, 'true', 'yes', 1, '1'], true)) {
1591 return true;
1592 }
1593 if (in_array($param, [false, 'false', 'no', 0, '0'], true)) {
1594 return false;
1595 }
1596 return (bool) $default;
1597 }
1598
1599 public static function has_allowed_roles($allowed_roles = [])
1600 {
1601
1602 if (empty($allowed_roles) || (count($allowed_roles) == 1 && empty($allowed_roles[0]))) {
1603 return true;
1604 }
1605 $current_user = wp_get_current_user();
1606 $user_roles = $current_user->roles;
1607
1608 return !empty(array_intersect($user_roles, $allowed_roles));
1609 }
1610
1611 public static function get_elementor_global_color($settings, $key)
1612 {
1613
1614 $global_color = $settings[$key];
1615
1616 if (isset($settings['__globals__'][$key])) {
1617 $color_setting = $settings['__globals__'][$key];
1618
1619 if (strpos($color_setting, 'globals/colors?id=') === 0) {
1620 // It's a global color reference
1621 $global_id = str_replace('globals/colors?id=', '', $color_setting);
1622
1623 $kit = Plugin::$instance->kits_manager->get_current_settings();
1624
1625 $system_colors = isset($kit['system_colors']) ? $kit['system_colors'] : [];
1626 $custom_colors = isset($kit['custom_colors']) ? $kit['custom_colors'] : [];
1627 $global_colors = array_merge($system_colors, $custom_colors);
1628
1629 foreach ($global_colors as $color) {
1630
1631 if ($color['_id'] === $global_id) {
1632 $global_color = $color['color']; // Found a match, set the color
1633 break;
1634 }
1635 }
1636 }
1637 }
1638 return $global_color;
1639 }
1640
1641 public static function get_provider_name($source_url)
1642 {
1643 if (self::is_youtube_channel($source_url)) {
1644 $source_name = 'YoutubeChannel';
1645 } else if (self::is_youtube($source_url)) {
1646 $source_name = 'Youtube';
1647 } else if (!empty(self::is_file_url($source_url))) {
1648 $source_name = 'document_' . self::get_extension_from_file_url($source_url);
1649 } else if (self::is_opensea($source_url)) {
1650 $source_name = 'OpenSea';
1651 } else if (self::is_instagram_feed($source_url)) {
1652 $source_name = 'InstagramFeed';
1653 }else {
1654 Shortcode::get_embera_instance();
1655 $collectios = Shortcode::get_collection();
1656 $provider = $collectios->findProviders($source_url);
1657
1658 if (!empty($provider[$source_url])) {
1659 $source_name = $provider[$source_url]->getProviderName();
1660 } else {
1661 $host = parse_url($source_url, PHP_URL_HOST);
1662 if ($host) {
1663 $parts = explode('.', $host);
1664 if (count($parts) > 1) {
1665 $source_name = $parts[1];
1666 } else {
1667 // Handle the case where the host doesn't have at least two parts
1668 $source_name = $host;
1669 }
1670 } else {
1671 // Handle the case where parse_url fails
1672 $source_name = '';
1673 }
1674 }
1675 }
1676
1677 return $source_name;
1678 }
1679
1680 public static function get_user_roles()
1681 {
1682 global $wp_roles; // Access global roles object
1683 $user_roles = [];
1684
1685 if (isset($wp_roles->roles) && is_array($wp_roles->roles)) {
1686 foreach ($wp_roles->roles as $role_key => $role_data) {
1687 $user_roles[] = [
1688 'value' => $role_key, // Machine-readable key
1689 'label' => $role_data['name'], // Human-readable name
1690 ];
1691 }
1692 }
1693
1694 return $user_roles;
1695 }
1696
1697 public static function has_content_allowed_roles($allowed_roles = [])
1698 {
1699 // Ensure it's always an array
1700 if (!is_array($allowed_roles)) {
1701 $allowed_roles = [];
1702 }
1703
1704 if (count($allowed_roles) === 1 && empty($allowed_roles[0])) {
1705 return true;
1706 }
1707
1708 $current_user = wp_get_current_user();
1709 $user_roles = $current_user->roles;
1710
1711 return !empty(array_intersect($user_roles, $allowed_roles));
1712 }
1713
1714
1715 }
1716