PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more / 4.4.3
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more v4.4.3
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 9 months ago Database 9 months ago Elementor_Enhancer.php 1 year ago EmbedPress_Core_Installer.php 6 years ago EmbedPress_Notice.php 2 years ago EmbedPress_Plugin_Usage_Tracker.php 1 year ago Extend_CustomPlayer_Controls.php 1 year ago Extend_Elementor_Controls.php 1 year ago Feature_Enhancer.php 9 months ago Helper.php 9 months ago PermalinkHelper.php 10 months ago
Helper.php
1722 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_extension_from_file_url($url)
129 {
130 $urlSplit = explode(".", $url);
131 $ext = end($urlSplit);
132 return $ext;
133 }
134
135 public static function is_file_url($url)
136 {
137 $pattern = '/\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/i';
138 return preg_match($pattern, $url) === 1;
139 }
140
141 public static function is_opensea($url)
142 {
143 return strpos($url, "opensea.io") !== false;
144 }
145 public static function is_youtube_channel($url)
146 {
147 return (bool) (preg_match('~(?:https?:\/\/)?(?:www\.)?(?:youtube.com\/)(?:channel\/|c\/|user\/|@)(\w+)~i', (string) $url));
148 }
149
150 public static function is_youtube($url)
151 {
152 return (bool) (preg_match('~(?:https?://)?(?:www\.)?(?:youtube\.com|youtu\.be)/watch\?v=([^&]+)~i', (string) $url));
153 }
154
155 // Saved sources data temporary in wp_options table
156 public static function get_source_data($blockid, $source_url, $source_option_name, $source_temp_option_name)
157 {
158
159
160 if (self::is_youtube_channel($source_url)) {
161 $source_name = 'YoutubeChannel';
162 } else if (self::is_youtube($source_url)) {
163 $source_name = 'Youtube';
164 } else if (!empty(self::is_file_url($source_url))) {
165 $source_name = 'document_' . self::get_extension_from_file_url($source_url);
166 } else if (self::is_opensea($source_url)) {
167 $source_name = 'OpenSea';
168 } else {
169 Shortcode::get_embera_instance();
170 $collectios = Shortcode::get_collection();
171 $provider = $collectios->findProviders($source_url);
172
173 if (!empty($provider[$source_url])) {
174 $source_name = $provider[$source_url]->getProviderName();
175 } else {
176 $host = parse_url($source_url, PHP_URL_HOST);
177 if ($host) {
178 $parts = explode('.', $host);
179 if (count($parts) > 1) {
180 $source_name = $parts[1];
181 } else {
182 // Handle the case where the host doesn't have at least two parts
183 $source_name = $host;
184 }
185 } else {
186 // Handle the case where parse_url fails
187 $source_name = 'unknown';
188 }
189 }
190 }
191
192 if (!empty($blockid) && $blockid != 'undefined') {
193 $sources = json_decode(get_option($source_temp_option_name), true);
194
195 if (!$sources) {
196 $sources = array();
197 }
198 $exists = false;
199
200 foreach ($sources as $i => $source) {
201 if ($source['id'] === $blockid) {
202 $sources[$i]['source']['name'] = $source_name;
203 $sources[$i]['source']['url'] = $source_url;
204 $exists = true;
205 break;
206 }
207 }
208
209 if (!$exists) {
210 $sources[] = array('id' => $blockid, 'source' => array('name' => $source_name, 'url' => $source_url, 'count' => 1));
211 }
212
213 update_option($source_temp_option_name, json_encode($sources));
214 }
215 }
216
217 // Saved source data when post updated
218 public static function get_save_source_data_on_post_update($source_option_name, $source_temp_option_name)
219 {
220
221 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
222 return;
223 }
224 $temp_data = json_decode(get_option($source_temp_option_name), true);
225 $source_data = json_decode(get_option($source_option_name), true);
226 if (!$temp_data) {
227 $temp_data = array();
228 }
229 if (!$source_data) {
230 $source_data = array();
231 }
232
233 $sources = array_merge($temp_data, $source_data);
234
235 $unique_sources = array();
236 foreach ($sources as $source) {
237 $unique_sources[$source['id']] = $source;
238 }
239
240 $unique_sources = array_values($unique_sources);
241
242 delete_option($source_temp_option_name);
243
244 update_option($source_option_name, json_encode($unique_sources));
245 }
246
247 //Delete source data from option table when widget is removed
248 public static function get_delete_source_data($blockid, $source_option_name, $source_temp_option_name)
249 {
250 if (!empty($blockid) && $blockid != 'undefined') {
251 $sources = json_decode(get_option($source_option_name), true);
252 $temp_sources = json_decode(get_option($source_temp_option_name), true);
253 if ($sources) {
254 foreach ($sources as $i => $source) {
255 if ($source['id'] === $blockid) {
256 unset($sources[$i]);
257 break;
258 }
259 }
260 update_option($source_option_name, json_encode(array_values($sources)));
261 }
262 if ($temp_sources) {
263 foreach ($temp_sources as $i => $source) {
264 if ($source['id'] === $blockid) {
265 unset($temp_sources[$i]);
266 break;
267 }
268 }
269 update_option($source_temp_option_name, json_encode(array_values($temp_sources)));
270 }
271 }
272 wp_die();
273 }
274
275 //Delete source temporary data when reload without update or publish
276 public static function get_delete_source_temp_data_on_reload($source_temp_option_name)
277 {
278 $source_temp_data = json_decode(get_option($source_temp_option_name), true);
279 if ($source_temp_data) {
280 delete_option($source_temp_option_name);
281 }
282 }
283
284 public static function get_file_title($url)
285 {
286 return get_the_title(attachment_url_to_postid($url));
287 }
288
289 public static function get_hash()
290 {
291 $hash_key = get_option(EMBEDPRESS_PLG_NAME . '_hash_key');
292 if (!$hash_key) {
293 $hash_key = wp_hash_password(wp_generate_password(30));
294 update_option(EMBEDPRESS_PLG_NAME . '_hash_key', $hash_key);
295 }
296 return $hash_key;
297 }
298
299 public function lock_content_form_handler() {
300 // print_r($embedHTML);
301
302 $client_id = isset($_POST['client_id']) ? sanitize_text_field($_POST['client_id']) : '';
303 $password = isset($_POST['password']) ? sanitize_text_field($_POST['password']) : '';
304 $post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
305
306 $epbase64 = get_post_meta( $post_id, 'ep_base_' .$client_id, true );
307 $hash_key = get_post_meta( $post_id, 'hash_key_' .$client_id, true );
308
309 // Set the decryption key and initialization vector (IV)
310 $key = Helper::get_hash();
311
312 // Decode the base64 encoded cipher
313 $cipher = base64_decode($epbase64);
314 // Decrypt the cipher using AES-128-CBC encryption
315
316 $wp_pass_key = hash('sha256', wp_salt(32) . md5($password));
317 $iv = substr($wp_pass_key, 0, 16);
318
319 if ($wp_pass_key === $hash_key) {
320
321 $embed = openssl_decrypt($cipher, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv) . '<script>
322 var now = new Date();
323 var time = now.getTime();
324 var expireTime = time + 1000 * 60 * 60 * 24 * 30;
325 now.setTime(expireTime);
326 document.cookie = "password_correct_'.esc_js($client_id).'='.esc_js($hash_key).'; expires=" + now.toUTCString() + "; path=/";
327 </script>';
328
329 }
330 else{
331 $embed = 0;
332 }
333
334 // Process the form data and return a response
335 $response = array(
336 'success' => true,
337 'password' => $password,
338 'embedHtml' => $embed,
339 'post_id' => $post_id
340 );
341
342 wp_send_json($response);
343
344 }
345
346 public function gutenberg_password_check()
347 {
348 $client_id = isset($_POST['client_id']) ? sanitize_text_field($_POST['client_id']) : '';
349 $password = isset($_POST['password']) ? sanitize_text_field($_POST['password']) : '';
350 $content_password = isset($_POST['content_password']) ? sanitize_text_field($_POST['content_password']) : '';
351
352 // Verify password
353 if ($password === $content_password) {
354 // Set cookie for authentication
355 $hash_pass = hash('sha256', wp_salt(32) . md5($password));
356 setcookie("password_correct_" . $client_id, $hash_pass, time() + 3600, '/');
357
358 $response = array(
359 'success' => true,
360 'message' => 'Password correct'
361 );
362 } else {
363 $response = array(
364 'success' => false,
365 'message' => 'Incorrect password'
366 );
367 }
368
369 wp_send_json($response);
370 }
371
372 public static function display_password_form($client_id = '', $embedHtml = '', $pass_hash_key = '', $attributes = [])
373 {
374 $lock_heading = !empty($attributes['lockHeading']) ? sanitize_text_field($attributes['lockHeading']) : '';
375 $lock_subheading = !empty($attributes['lockSubHeading']) ? sanitize_text_field($attributes['lockSubHeading']) : '';
376 $lock_error_message = !empty($attributes['lockErrorMessage']) ? sanitize_text_field($attributes['lockErrorMessage']) : '';
377 $footer_message = !empty($attributes['footerMessage']) ? sanitize_text_field($attributes['footerMessage']) : '';
378 $password_placeholder = !empty($attributes['passwordPlaceholder']) ? sanitize_text_field($attributes['passwordPlaceholder']) : '';
379 $button_text = !empty($attributes['submitButtonText']) ? sanitize_text_field($attributes['submitButtonText']) : '';
380 $unlocking_text = !empty($attributes['submitUnlockingText']) ? sanitize_text_field($attributes['submitUnlockingText']) : '';
381 $enable_footer_message = !empty($attributes['enableFooterMessage']) ? sanitize_text_field($attributes['enableFooterMessage']) : '';
382
383
384 // Set the encryption key and initialization vector (IV)
385 $key = self::get_hash();
386
387 $salt = wp_salt(32);
388 $wp_hash_key = hash('sha256', $salt . $pass_hash_key);
389 $iv = substr($wp_hash_key, 0, 16);
390
391
392 // Encrypt the plaintext using AES-128-CBC encryption
393 $cipher = openssl_encrypt($embedHtml, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
394
395 // Base64 encode the encrypted cipher
396 $encrypted_data = base64_encode($cipher);
397
398 update_post_meta(get_the_ID(), 'ep_base_' . $client_id, $encrypted_data);
399 update_post_meta(get_the_ID(), 'hash_key_' . $client_id, $wp_hash_key);
400
401 $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>';
402
403 echo '
404 <div class="password-form-container">
405 <h2>' . esc_html($lock_heading) . '</h2>
406 <p>' . esc_html($lock_subheading) . ' </p>
407 <form class="password-form" method="post" class="password-form" data-unlocking-text="' . esc_attr($unlocking_text) . '">
408
409 <div class="password-field">
410 <span class="lock-icon">' . $lock_icon . '</span>
411 <input type="password" name="pass_' . esc_attr($client_id) . '" placeholder="' . esc_attr($password_placeholder) . '" required>
412 </div>
413 <input type="hidden" name="ep_client_id" value="' . esc_attr($client_id) . '">
414 <input type="hidden" name="post_id" value="' . esc_attr(get_the_ID()) . '">
415
416 <input type="submit" name="password_submit" value="' . esc_attr($button_text) . '">
417 <div class="error-message hidden">' . esc_html($lock_error_message) . '</div>
418 </form>
419 ' . (!empty($enable_footer_message) ? '<p class="need-access-message">' . esc_html($footer_message) . '</p>' : '') . '
420 </div>
421 ';
422 }
423
424 // Check if the user has already entered the correct password
425 public static function is_password_correct($client_id)
426 {
427 if (isset($_COOKIE['password_correct_' . $client_id])) {
428 return $_COOKIE['password_correct_' . $client_id];
429 } else {
430 return false;
431 }
432 }
433
434 public static function customLogo($embedHTML, $atts)
435 {
436 $x = !empty($atts['logoX']) ? $atts['logoX'] : 0;
437 $y = !empty($atts['logoY']) ? $atts['logoY'] : 0;
438 $uniqid = !empty($atts['url']) ? '.ose-uid-' . md5($atts['url']) : '';
439
440 $brandUrl = !empty($atts['customlogoUrl']) ? $atts['customlogoUrl'] : '';
441 $opacity = !empty($atts['logoOpacity']) ? $atts['logoOpacity'] : '';
442
443 $cssClass = !empty($atts['url']) ? '.ose-uid-' . md5($atts['url']) : '.ose-youtube';
444
445
446
447 ob_start(); ?>
448 <style type="text/css">
449 <?php echo esc_html($cssClass); ?> {
450 position: relative;
451 }
452
453 <?php echo esc_html($cssClass); ?>.watermark {
454 border: 0;
455 position: absolute;
456 bottom: <?php echo esc_html($y); ?>%;
457 right: <?php echo esc_html($x); ?>%;
458 max-width: 150px;
459 max-height: 75px;
460 opacity: 0.25;
461 z-index: 5;
462 -o-transition: opacity 0.5s ease-in-out;
463 -moz-transition: opacity 0.5s ease-in-out;
464 -webkit-transition: opacity 0.5s ease-in-out;
465 transition: opacity 0.5s ease-in-out;
466 opacity: <?php echo esc_html($opacity); ?>;
467 }
468
469 <?php echo esc_html($cssClass); ?>.watermark:hover {
470 opacity: 1;
471 }
472 </style>
473 <?php
474
475
476 $style = ob_get_clean();
477
478 if (!class_exists('\simple_html_dom')) {
479 include_once EMBEDPRESS_PATH_CORE . 'simple_html_dom.php';
480 }
481
482 $cta = '';
483 $img = '';
484
485 if (!empty($atts['customlogo'])) {
486 $img = '<img src="' . esc_url($atts['customlogo']) . '"/>';
487
488 $imgDom = str_get_html($img);
489 $imgDom = $imgDom->find('img', 0);
490 $imgDom->setAttribute('class', 'watermark ep-custom-logo');
491 $imgDom->removeAttribute('style');
492 $imgDom->setAttribute('width', 'auto');
493 $imgDom->setAttribute('height', 'auto');
494 ob_start();
495 echo $imgDom;
496
497 $cta .= ob_get_clean();
498
499 $imgDom->clear();
500 unset($img, $imgDom);
501
502 if (!empty($brandUrl)) {
503 $cta = '<a href="' . esc_url($brandUrl) . '" target="_blank">' . $cta . '</a>';
504 }
505 $dom = str_get_html($embedHTML);
506
507 $wrapDiv = $dom->find($uniqid, 0);
508
509 if (!empty($wrapDiv) && is_object($wrapDiv)) {
510 $wrapDiv->innertext .= $cta;
511 }
512
513 ob_start();
514 echo $wrapDiv;
515
516 $markup = ob_get_clean();
517
518 $dom->clear();
519 unset($dom, $wrapDiv);
520
521 $embedHTML = $style . $markup;
522 }
523
524 return $embedHTML;
525 }
526
527
528 public static function embed_content_share($content_id = '', $attributes = [])
529 {
530 $share_position = !empty($attributes['sharePosition']) ? $attributes['sharePosition'] : 'right';
531 $custom_thumnail = !empty($attributes['customThumbnail']) ? $attributes['customThumbnail'] : '';
532 $custom_title = !empty($attributes['customTitle']) ? $attributes['customTitle'] : '';
533 $custom_description = !empty($attributes['customDescription']) ? $attributes['customDescription'] : '';
534
535 // Create a unique hash based on content attributes
536 $content_hash = md5($custom_thumnail . $custom_title . $custom_description . $content_id);
537
538 // Encode for URL usage
539 $custom_thumnail = urlencode($custom_thumnail);
540 $custom_title = urlencode($custom_title);
541 $custom_description = urlencode($custom_description);
542
543 // Get social share options with defaults
544 $facebook_enabled = isset($attributes['shareFacebook']) ? $attributes['shareFacebook'] !== false : true;
545 $twitter_enabled = isset($attributes['shareTwitter']) ? $attributes['shareTwitter'] !== false : true;
546 $pinterest_enabled = isset($attributes['sharePinterest']) ? $attributes['sharePinterest'] !== false : true;
547 $linkedin_enabled = isset($attributes['shareLinkedin']) ? $attributes['shareLinkedin'] !== false : true;
548 $style = isset($attributes['width']) ? 'style="max-width: ' . esc_attr($attributes['width']) . 'px;"' : '';
549
550
551 $page_url = urlencode(get_permalink() . '?hash=' . $content_id . '&unique=' . $content_hash);
552
553 $social_icons = '<div class="ep-social-share-wraper"' . $style . ' ><div class="ep-social-share share-position-' . esc_attr($share_position) . '">';
554
555
556 // Facebook
557 if ($facebook_enabled) {
558 $social_icons .= '<a href="https://www.facebook.com/sharer/sharer.php?u=' . $page_url . '" class="ep-social-icon facebook" target="_blank">
559 <svg width="64px" height="64px" fill="#000000" viewBox="0 -6 512 512" xmlns="http://www.w3.org/2000/svg">
560 <path d="M0 0h512v500H0z" fill="#475a96"/>
561 <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"/>
562 </svg>
563 </a>';
564 }
565
566 // Twitter
567 if ($twitter_enabled) {
568 $social_icons .= '<a href="https://twitter.com/intent/tweet?url=' . $page_url . '&text=' . $custom_title . '" class="ep-social-icon twitter" target="_blank">
569 <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>
570 </a>';
571 }
572
573 // Pinterest
574 if ($pinterest_enabled) {
575 $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">
576
577 <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>
578
579 </a>';
580 }
581
582 // LinkedIn
583 if ($linkedin_enabled) {
584 $social_icons .= '<a href="https://www.linkedin.com/shareArticle?mini=true&url=' . $page_url . '" class="ep-social-icon linkedin" target="_blank">
585
586 <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"
587 viewBox="0 0 310 310" xml:space="preserve">
588 <g id="XMLID_801_">
589 <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
590 C77.16,101.969,74.922,99.73,72.16,99.73z"/>
591 <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
592 c22.626,0,41.033-18.41,41.033-41.038C82.1,18.743,63.692,0.341,41.066,0.341z"/>
593 <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
594 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
595 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
596 C310,145.43,300.549,94.761,230.454,94.761z"/>
597 </g>
598 </svg>
599 </a>';
600 }
601
602 $social_icons .= '</div></div>';
603
604 return $social_icons;
605 }
606
607 public static function ep_get_elementor_widget_settings($page_settings = '', $id = '', $widgetType = '')
608 {
609 if (empty($page_settings)) {
610 return [];
611 }
612
613 // Handle both string and array cases for elementor data
614 if (is_string($page_settings)) {
615 $data = json_decode($page_settings, true);
616 } else {
617 // Data might already be an array in older versions
618 $data = $page_settings;
619 }
620 $element_setting = null;
621
622 Plugin::$instance->db->iterate_data($data, function ($element) use (&$element_setting, $widgetType, $id) {
623
624 if ($element['id'] == $id && $element['elType'] == 'widget' && $element['widgetType'] == $widgetType) {
625 $element_setting[] = $element['settings'];
626 }
627 });
628
629 return $element_setting;
630 }
631
632
633
634 public static function ep_get_popup_icon()
635 {
636 $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>';
637
638 return $svg;
639 }
640 public static function ep_get_download_icon()
641 {
642 $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>';
643
644 return $svg;
645 }
646
647 public static function ep_get_print_icon()
648 {
649 $svg = '<div class="ep-doc-print-icon" ><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24">
650 <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"/>
651 </svg></div>';
652
653 return $svg;
654 }
655
656 public static function ep_get_fullscreen_icon()
657 {
658 $svg = '<div class="ep-doc-fullscreen-icon"><svg width="25" height="25" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
659 <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"/>
660 </svg></div>';
661
662 return $svg;
663 }
664 public static function ep_get_minimize_icon()
665 {
666 $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>';
667
668 return $svg;
669 }
670 public static function ep_get_draw_icon()
671 {
672 $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>';
673
674 return $svg;
675 }
676
677 public static function get_insta_video_icon()
678 {
679 $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">
680 <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>';
681
682 return $svg;
683 }
684
685 public static function get_insta_image_carousel_icon()
686 {
687 $svg = '<svg aria-label="Carousel" class="x1lliihq x1n2onr6" color="#FFF" fill="#FFF" height="25" viewBox="0 0 43.636 43.636" width="25">
688 <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>';
689
690 return $svg;
691 }
692
693 public static function get_insta_image_icon()
694 {
695 $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>';
696
697 return $svg;
698 }
699
700 public static function get_insta_like_icon()
701 {
702 $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>';
703
704 return $svg;
705 }
706 public static function get_insta_comment_icon()
707 {
708 $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>';
709
710 return $svg;
711 }
712 public static function get_instagram_icon()
713 {
714 $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>';
715
716 return $svg;
717 }
718
719 public static function get_google_presentation_url($embedded_url)
720 {
721 $parsed_url = parse_url($embedded_url);
722 $base_url = $parsed_url['scheme'] . '://' . $parsed_url['host'] . $parsed_url['path'];
723 $base_url = strtok($base_url, '?');
724 $base_url = rtrim($base_url, '/');
725 return $base_url;
726 }
727
728 public static function check_media_format($url)
729 {
730 $pattern1 = '/\.(mp4|mov|avi|wmv|flv|mkv|webm|mpeg|mpg)$/i';
731 $pattern2 = '/\.(mp3|wav|ogg|aac)$/i';
732
733 $isVideo = preg_match($pattern1, $url);
734 $isAudio = preg_match($pattern2, $url);
735
736 $is_self_hosted = false;
737 $format = '';
738
739 if (!empty($isVideo) || !empty($isAudio)) {
740 $is_self_hosted = true;
741 if (!empty($isVideo)) {
742 $format = 'video';
743 } else if (!empty($isAudio)) {
744 $format = 'audio';
745 }
746 }
747
748 if (!$is_self_hosted) {
749 return [
750 'selhosted' => false,
751 ];
752 }
753
754 return [
755 'selhosted' => true,
756 'format' => $format,
757 ];
758 }
759
760 // Ajax Methods get instagram feed data
761 public function loadmore_data_handler()
762 {
763 $connected_account_type = isset($_POST['connected_account_type']) ? sanitize_text_field($_POST['connected_account_type']) : 'personal';
764 $hashtag_id = isset($_POST['hashtag_id']) ? sanitize_text_field($_POST['hashtag_id']) : '';
765 $feed_type = isset($_POST['feed_type']) ? sanitize_text_field($_POST['feed_type']) : 'user_aacount_type';
766 $user_id = isset($_POST['user_id']) ? sanitize_text_field($_POST['user_id']) : '';
767 $loadmore_key = isset($_POST['loadmore_key']) ? sanitize_text_field($_POST['loadmore_key']) : '';
768 $nonce = isset($_POST['_nonce']) ? sanitize_text_field($_POST['_nonce']) : '';
769 $params = isset($_POST['params']) ? sanitize_text_field($_POST['params']) : '';
770 // $params = json_decode($params, true);
771 $params = stripslashes($params); // Remove extra backslashes
772 $params = json_decode($params, true);
773
774 // Verify nonce
775 if (!wp_verify_nonce($nonce, 'ep_nonce')) {
776 wp_send_json_error('Invalid nonce');
777 wp_die(); // Terminate script execution if nonce is invalid
778 }
779
780 $feeds_data = get_option('ep_instagram_feed_data');
781 $user_data = $feeds_data[$user_id]['feed_userinfo'];
782
783 if ($feed_type == 'hashtag_type') {
784 $feeds_data = get_option('ep_instagram_hashtag_feed');
785 }
786
787
788 $profile_picture_url = isset($user_data['profile_picture_url']) ? $user_data['profile_picture_url'] : '';
789
790 if ($feed_type === 'user_account_type' && isset($feeds_data[$loadmore_key]['feed_posts'])) {
791 $feed_posts = $feeds_data[$loadmore_key]['feed_posts'];
792 } else if ($feed_type === 'hashtag_type' && isset($feeds_data[$loadmore_key])) {
793 $feed_posts = $feeds_data[$loadmore_key];
794 } else {
795 $feed_posts = ['error'];
796 }
797
798
799 if (is_array($feed_posts) && count($feed_posts) > 0) {
800 $loaded_posts = isset($_POST['loaded_posts']) ? intval($_POST['loaded_posts']) : 0;
801 $posts_per_page = isset($_POST['posts_per_page']) ? intval($_POST['posts_per_page']) : 0;
802
803 $post_index = $loaded_posts + 1;
804 $start_index = $loaded_posts;
805
806 $next_posts = array_slice($feed_posts, $start_index, $posts_per_page);
807
808 ob_start();
809
810 if (is_array($next_posts) && count($next_posts) > 0) :
811 foreach ($next_posts as $post) :
812 $caption = !empty($post['caption']) ? $post['caption'] : '';
813 $media_type = !empty($post['media_type']) ? $post['media_type'] : '';
814 $media_url = !empty($post['media_url']) ? $post['media_url'] : '';
815 $permalink = !empty($post['permalink']) ? $post['permalink'] : '';
816 $timestamp = !empty($post['timestamp']) ? $post['timestamp'] : '';
817 $username = !empty($post['username']) ? $post['username'] : '';
818 $like_count = !empty($post['like_count']) ? $post['like_count'] : 0;
819 $comments_count = !empty($post['comments_count']) ? $post['comments_count'] : 0;
820
821 $post['profile_picture_url'] = $profile_picture_url;
822 $post['show_likes_count'] = isset($params['show_likes_count']) ? $params['show_likes_count'] : false;
823 $post['show_comments_count'] = isset($params['show_comments_count']) ? $params['show_comments_count'] : false;
824 $post['popup_follow_button'] = isset($params['popup_follow_button']) ? $params['popup_follow_button'] : true;
825 $post['popup_follow_button_text'] = isset($params['popup_follow_button_text']) ? $params['popup_follow_button_text'] : 'Follow';
826 ?>
827
828 <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); ?>">
829 <?php
830
831 if (!empty($hashtag_id) && $media_type == 'CAROUSEL_ALBUM') {
832 if (isset($post['children']['data'][0]['media_url'])) {
833 $hashtag_media_url = $post['children']['data'][0]['media_url'];
834 $hashtag_media_type = $post['children']['data'][0]['media_type'];
835
836 if ($hashtag_media_type == 'VIDEO') {
837 echo '<video class="insta-gallery-image" src="' . esc_url($hashtag_media_url) . '"></video>';
838 } else {
839 echo ' <img class="insta-gallery-image" src="' . esc_url($hashtag_media_url) . '" alt="' . esc_attr('image') . '">';
840 }
841 }
842 } else {
843 if ($media_type == 'VIDEO') {
844 echo '<video class="insta-gallery-image" src="' . esc_url($media_url) . '"></video>';
845 } else {
846 echo ' <img class="insta-gallery-image" src="' . esc_url($media_url) . '" alt="' . esc_attr('image') . '">';
847 }
848 }
849 ?>
850
851 <div class="insta-gallery-item-type">
852 <div class="insta-gallery-item-type-icon">
853 <?php
854 if ($media_type == 'VIDEO') {
855 echo Helper::get_insta_video_icon();
856 } else if ($media_type == 'CAROUSEL_ALBUM') {
857 echo Helper::get_insta_image_carousel_icon();
858 } else {
859 echo Helper::get_insta_image_icon();
860 }
861 ?>
862 </div>
863 </div>
864 <div class="insta-gallery-item-info">
865 <?php if (strtolower($connected_account_type) === 'business') : ?>
866 <div class="insta-item-reaction-count">
867 <div class="insta-gallery-item-likes">
868 <?php echo Helper::get_insta_like_icon();
869 echo esc_html($like_count); ?>
870 </div>
871 <div class="insta-gallery-item-comments">
872 <?php echo Helper::get_insta_comment_icon();
873 echo esc_html($comments_count); ?>
874 </div>
875 </div>
876 <?php else : ?>
877 <div class="insta-gallery-item-permalink">
878 <?php echo Helper::get_instagram_icon(); ?>
879 </div>
880 <?php endif; ?>
881 </div>
882 </div>
883
884 <?php $post_index++;
885 endforeach;
886 endif;
887
888 $feed_item = ob_get_clean();
889
890 $next_start_index = $start_index + count($next_posts);
891
892 wp_send_json(array(
893 'html' => $feed_item,
894 'next_post_index' => $next_start_index,
895 'total_feed_posts' => count($feed_posts)
896 ));
897 } else {
898 wp_send_json('');
899 }
900 }
901
902 public static function getCalendlyUuid($url)
903 {
904 $pattern = '/\/([0-9a-fA-F-]+)$/';
905 if (preg_match($pattern, $url, $matches)) {
906 $uuid = $matches[1];
907 return $uuid;
908 }
909 return '';
910 }
911
912 public static function getCalendlyUserInfo($access_token)
913 {
914 $transient_name = 'calendly_user_info_' . $access_token;
915 $user_info = get_transient($transient_name);
916 if (false === $user_info) {
917 $user_endpoint = 'https://api.calendly.com/users/me';
918 $headers = array(
919 'Authorization' => "Bearer $access_token",
920 'Content-Type' => 'application/json',
921 );
922 $args = array(
923 'headers' => $headers,
924 );
925 $response = wp_remote_get($user_endpoint, $args);
926 if (!is_wp_error($response) && 200 === wp_remote_retrieve_response_code($response)) {
927 $user_info = wp_remote_retrieve_body($response);
928 set_transient($transient_name, $user_info, 3600);
929 } else {
930 return false;
931 }
932 }
933
934 return $user_info;
935 }
936
937
938
939 public static function getCalaendlyEventTypes($user_uri, $access_token)
940 {
941 // Attempt to retrieve the data from the transient
942 $events_list = get_transient('calendly_events_list_' . md5($access_token));
943
944 if (false === $events_list) {
945 // If the data is not in the transient, fetch it from the API
946 $events_endpoint = "https://api.calendly.com/event_types?user=$user_uri";
947
948 $headers = array(
949 'Authorization' => "Bearer $access_token",
950 'Content-Type' => 'application/json',
951 );
952
953 $args = array(
954 'headers' => $headers,
955 );
956
957 $response = wp_remote_get($events_endpoint, $args);
958
959 if (!is_wp_error($response)) {
960 $body = wp_remote_retrieve_body($response);
961 $events_list = json_decode($body, true);
962
963 // Store the data in a transient for a specified time (e.g., 1 hour)
964 set_transient('calendly_events_list', $events_list, HOUR_IN_SECONDS);
965
966 return $events_list;
967 }
968 }
969
970 return $events_list;
971 }
972
973 public static function getListEventInvitee($uuid, $access_token)
974 {
975 // Attempt to retrieve the data from the transient
976 $invitee_list = get_transient('calendly_invitee_list_' . md5($access_token));
977
978 if (false === $invitee_list) {
979 // If the data is not in the transient, fetch it from the API
980 $events_endpoint = "https://api.calendly.com/scheduled_events/$uuid/invitees";
981
982 $headers = array(
983 'Authorization' => "Bearer $access_token",
984 'Content-Type' => 'application/json',
985 );
986
987 $args = array(
988 'headers' => $headers,
989 );
990
991 $response = wp_remote_get($events_endpoint, $args);
992
993 if (!is_wp_error($response)) {
994 $body = wp_remote_retrieve_body($response);
995 $invitee_list = json_decode($body, true);
996
997 // Store the data in a transient for a specified time (e.g., 1 hour)
998 set_transient('calendly_invitee_list', $invitee_list, HOUR_IN_SECONDS);
999
1000 return $invitee_list;
1001 }
1002 }
1003
1004 return $invitee_list;
1005 }
1006
1007 public static function getCalaendlyScheduledEvents($user_uri, $access_token)
1008 {
1009 // Attempt to retrieve the data from the transient
1010 $events_list = get_transient('calendly_events_list_' . md5($access_token));
1011
1012 if (false === $events_list) {
1013 // If the data is not in the transient, fetch it from the API
1014 $events_endpoint = "https://api.calendly.com/scheduled_events?user=$user_uri";
1015
1016 $headers = array(
1017 'Authorization' => "Bearer $access_token",
1018 'Content-Type' => 'application/json',
1019 );
1020
1021 $args = array(
1022 'headers' => $headers,
1023 );
1024
1025 $response = wp_remote_get($events_endpoint, $args);
1026
1027 if (!is_wp_error($response)) {
1028 $body = wp_remote_retrieve_body($response);
1029 $events_list = json_decode($body, true);
1030
1031 // Store the data in a transient for a specified time (e.g., 1 hour)
1032 set_transient('calendly_events_list', $events_list, HOUR_IN_SECONDS);
1033
1034 return $events_list;
1035 }
1036 }
1037
1038 return $events_list;
1039 }
1040
1041
1042 public static function parseDuration($durationString)
1043 {
1044 list($minutes, $seconds) = explode(':', $durationString);
1045 return intval($minutes) * 60 + intval($seconds);
1046 }
1047
1048
1049
1050
1051 public static function is_pro_active()
1052 {
1053 if (defined('EMBEDPRESS_SL_ITEM_SLUG')) {
1054 return true;
1055 }
1056 return false;
1057 }
1058
1059 /**
1060 * Check if pro features should be enabled based on license status
1061 *
1062 * @return bool True if pro features should be enabled, false otherwise
1063 */
1064 public static function is_pro_features_enabled()
1065 {
1066 // First check if pro plugin is active
1067 if (!self::is_pro_active()) {
1068 return false;
1069 }
1070
1071 // Get license status
1072 $license_status = get_option('embedpress_pro_software__license_status', '');
1073
1074 // Pro features are enabled only if license is valid
1075 return $license_status === 'valid';
1076 }
1077
1078 /**
1079 * Get detailed license information
1080 *
1081 * @return array License information including status, key, and data
1082 */
1083 public static function get_license_info()
1084 {
1085 $is_pro_active = self::is_pro_active();
1086 $license_status = '';
1087 $license_key = '';
1088 $license_data = [];
1089 $is_features_enabled = false;
1090
1091 if ($is_pro_active) {
1092 $license_status = get_option('embedpress_pro_software__license_status', '');
1093 $license_data_raw = get_transient('embedpress_pro_software__license_data');
1094
1095 if ($license_data_raw) {
1096 $license_data = json_decode(json_encode($license_data_raw), true);
1097 $license_key = isset($license_data['license_key']) ? $license_data['license_key'] : '';
1098 }
1099
1100 $is_features_enabled = ($license_status === 'valid');
1101 }
1102
1103 return [
1104 'is_pro_active' => $is_pro_active,
1105 'license_status' => $license_status,
1106 'license_key' => $license_key,
1107 'license_data' => $license_data,
1108 'is_features_enabled' => $is_features_enabled,
1109 'status_message' => self::get_license_status_message($is_pro_active, $license_status)
1110 ];
1111 }
1112
1113 /**
1114 * Display license warning notice for pro features
1115 *
1116 * @param string $context Context where the notice is displayed (e.g., 'analytics', 'branding')
1117 * @return string HTML for the license warning notice
1118 */
1119 public static function get_pro_feature_notice($context = '')
1120 {
1121 $license_info = self::get_license_info();
1122
1123 if (!$license_info['is_pro_active']) {
1124 return '<div class="embedpress-pro-notice embedpress-notice-warning">
1125 <p><strong>' . __('EmbedPress Pro Required', 'embedpress') . '</strong></p>
1126 <p>' . __('This feature requires EmbedPress Pro. Please install and activate EmbedPress Pro to access this feature.', 'embedpress') . '</p>
1127 </div>';
1128 }
1129
1130 if (!$license_info['is_features_enabled']) {
1131 $message = $license_info['status_message'];
1132 $action_text = '';
1133 $action_link = admin_url('admin.php?page=embedpress&page_type=license');
1134
1135 switch ($license_info['license_status']) {
1136 case 'expired':
1137 $action_text = __('Renew License', 'embedpress');
1138 break;
1139 case 'invalid':
1140 case 'site_inactive':
1141 case 'disabled':
1142 case 'revoked':
1143 $action_text = __('Activate License', 'embedpress');
1144 break;
1145 default:
1146 $action_text = __('Activate License', 'embedpress');
1147 break;
1148 }
1149
1150 return '<div class="embedpress-pro-notice embedpress-notice-error">
1151 <p><strong>' . __('Pro Features Disabled', 'embedpress') . '</strong></p>
1152 <p>' . esc_html($message) . '</p>
1153 <p><a href="' . esc_url($action_link) . '" class="button button-primary">' . esc_html($action_text) . '</a></p>
1154 </div>';
1155 }
1156
1157 return '';
1158 }
1159
1160 /**
1161 * Initialize license checking hooks
1162 */
1163 public static function init_license_hooks()
1164 {
1165 // Add filter to disable pro features when license is not valid
1166 add_filter('embedpress_pro_features_enabled', [__CLASS__, 'is_pro_features_enabled']);
1167
1168 // Add action to show license notices in admin
1169 add_action('admin_notices', [__CLASS__, 'show_license_admin_notices']);
1170
1171 // Add styles for license notices
1172 add_action('admin_head', [__CLASS__, 'add_license_notice_styles']);
1173 }
1174
1175 /**
1176 * Show license admin notices
1177 */
1178 public static function show_license_admin_notices()
1179 {
1180 // Only show on EmbedPress admin pages
1181 if (!isset($_GET['page']) || $_GET['page'] !== 'embedpress') {
1182 return;
1183 }
1184
1185 $license_info = self::get_license_info();
1186
1187 if ($license_info['is_pro_active'] && !$license_info['is_features_enabled']) {
1188 $message = $license_info['status_message'];
1189 $action_link = admin_url('admin.php?page=embedpress&page_type=license');
1190 $action_text = $license_info['license_status'] === 'expired' ? __('Renew License', 'embedpress') : __('Activate License', 'embedpress');
1191
1192 echo '<div class="notice notice-warning is-dismissible">
1193 <p><strong>' . __('EmbedPress Pro Features Disabled', 'embedpress') . '</strong></p>
1194 <p>' . esc_html($message) . '</p>
1195 <p><a href="' . esc_url($action_link) . '" class="button button-primary">' . esc_html($action_text) . '</a></p>
1196 </div>';
1197 }
1198 }
1199
1200 /**
1201 * Add CSS styles for license notices
1202 */
1203 public static function add_license_notice_styles()
1204 {
1205 echo '<style>
1206 .embedpress-pro-notice {
1207 padding: 15px;
1208 margin: 15px 0;
1209 border-left: 4px solid #dc3545;
1210 background: #fff;
1211 box-shadow: 0 1px 1px rgba(0,0,0,.04);
1212 }
1213 .embedpress-pro-notice.embedpress-notice-warning {
1214 border-left-color: #ffb900;
1215 }
1216 .embedpress-pro-notice.embedpress-notice-error {
1217 border-left-color: #dc3545;
1218 }
1219 .embedpress-pro-notice p {
1220 margin: 0.5em 0;
1221 }
1222 .embedpress-pro-notice strong {
1223 color: #23282d;
1224 }
1225 .embedpress-text-error {
1226 color: #dc3545 !important;
1227 }
1228 .embedpress-text-warning {
1229 color: #ffb900 !important;
1230 }
1231 </style>';
1232 }
1233
1234 /**
1235 * Get user-friendly license status message
1236 *
1237 * @param bool $is_pro_active Whether pro plugin is active
1238 * @param string $license_status Current license status
1239 * @return string User-friendly status message
1240 */
1241 public static function get_license_status_message($is_pro_active, $license_status)
1242 {
1243 if (!$is_pro_active) {
1244 return __('EmbedPress Pro is not installed or activated.', 'embedpress');
1245 }
1246
1247 switch ($license_status) {
1248 case 'valid':
1249 return __('Your license is active and valid.', 'embedpress');
1250 case 'expired':
1251 return __('Your license has expired. Please renew to continue receiving updates and support.', 'embedpress');
1252 case 'invalid':
1253 case 'site_inactive':
1254 return __('Your license is not active for this URL. Please activate your license.', 'embedpress');
1255 case 'disabled':
1256 case 'revoked':
1257 return __('Your license key has been disabled or revoked.', 'embedpress');
1258 case 'missing':
1259 return __('License key is missing. Please enter your license key.', 'embedpress');
1260 case 'http_error':
1261 return __('Unable to verify license due to connection issues. Please try again later.', 'embedpress');
1262 case '':
1263 case false:
1264 default:
1265 return __('Please activate your license key to enable EmbedPress Pro features.', 'embedpress');
1266 }
1267 }
1268
1269
1270 public static function getInstagramUserInfo($accessToken, $accountType, $userId, $is_sync = false)
1271 {
1272 if ($is_sync) {
1273 // If $is_sync is true, don't use transient
1274 $use_transient = false;
1275 } else {
1276 // If $is_sync is false, use transient
1277 $transient_key = 'instagram_user_info_' . $userId;
1278 $use_transient = true;
1279 }
1280
1281 if ($use_transient && false !== ($userInfo = get_transient($transient_key))) {
1282 // If transient exists, return cached user info
1283 return $userInfo;
1284 }
1285
1286 if (strtolower($accountType) === 'business') {
1287 $api_url = 'https://graph.facebook.com/' . $userId . '?fields=biography,id,username,website,followers_count,media_count,profile_picture_url,name&access_token=' . $accessToken;
1288 } else {
1289 $api_url = "https://graph.instagram.com/me?fields=id,username,account_type,media_count,followers_count,biography,website&access_token={$accessToken}";
1290 }
1291
1292 $connected_account_type = $accountType;
1293
1294 $userInfoResponse = wp_remote_get($api_url);
1295
1296 if (is_wp_error($userInfoResponse)) {
1297 echo 'Error: Unable to retrieve Instagram user information.';
1298 } else {
1299 $userInfoBody = wp_remote_retrieve_body($userInfoResponse);
1300 $userInfo = json_decode($userInfoBody, true);
1301
1302 $userInfo['connected_account_type'] = $connected_account_type;
1303 $userInfo['access_token'] = $accessToken;
1304
1305
1306 if (!isset($userInfo['profile_picture_url'])) {
1307 $userInfo['profile_picture_url'] = '';
1308 }
1309
1310 // If not using transient, cache the user info for an hour
1311 if ($use_transient) {
1312 set_transient($transient_key, $userInfo, HOUR_IN_SECONDS);
1313 }
1314
1315 return $userInfo;
1316 }
1317 }
1318
1319
1320 // Get Instagram posts, videos, reels
1321 public static function getInstagramPosts($access_token, $account_type, $userId, $limit = 100, $is_sync = false)
1322 {
1323 if ($is_sync) {
1324 // If $is_sync is true, don't use transient
1325 $use_transient = false;
1326 } else {
1327 // If $is_sync is false, use transient
1328 $transient_key = 'instagram_posts_' . $userId;
1329 $use_transient = true;
1330 }
1331
1332 if ($use_transient && false !== ($posts = get_transient($transient_key))) {
1333 // If transient exists, return cached posts
1334 return $posts;
1335 }
1336
1337 if (strtolower($account_type) === 'business') {
1338 $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;
1339 } else {
1340 $api_url = "https://graph.instagram.com/me/media?fields=id,caption,media_type,media_url,children{media_url,id,media_type},permalink,timestamp,username,thumbnail_url&limit=$limit&access_token=$access_token";
1341 }
1342
1343 $postsResponse = wp_remote_get($api_url);
1344
1345 if (is_wp_error($postsResponse)) {
1346 echo 'Error: Unable to retrieve Instagram posts.';
1347 } else {
1348 $postsBody = wp_remote_retrieve_body($postsResponse);
1349 $posts = json_decode($postsBody, true);
1350
1351 if (empty($posts['data'])) {
1352 return 'Please add Instagram Access Token';
1353 }
1354
1355 // If not using transient, cache the posts for an hour
1356 if ($use_transient) {
1357 set_transient($transient_key, $posts['data'], HOUR_IN_SECONDS);
1358 }
1359
1360 return $posts['data'];
1361 }
1362 }
1363
1364 public static function get_enable_settings_data_for_scripts($settings)
1365 {
1366 $settings_data = [
1367 'enabled_ads' => isset($settings['adManager']) && $settings['adManager'] === 'yes' ? 'yes' : '',
1368
1369 'enabled_custom_player' => isset($settings['emberpress_custom_player']) && $settings['emberpress_custom_player'] === 'yes' ? 'yes' : '',
1370
1371 'enabled_instafeed' => isset($settings['embedpress_pro_embeded_source']) && $settings['embedpress_pro_embeded_source'] === 'instafeed' ? 'yes' : '',
1372
1373 'enabled_docs_custom_viewer' => isset($settings['embedpress_document_viewer']) && $settings['embedpress_document_viewer'] === 'custom' ? 'yes' : '',
1374 ];
1375
1376 update_option('enabled_elementor_scripts', $settings_data);
1377 }
1378
1379 public static function get_options_value($key)
1380 {
1381 $g_settings = get_option(EMBEDPRESS_PLG_NAME);
1382
1383 if (isset($g_settings['enableEmbedResizeWidth']) && $g_settings['enableEmbedResizeWidth'] == 1) {
1384 $g_settings['enableEmbedResizeWidth'] = 600;
1385 update_option(EMBEDPRESS_PLG_NAME, $g_settings);
1386 }
1387 if (isset($g_settings['enableEmbedResizeHeight']) && $g_settings['enableEmbedResizeHeight'] == 1) {
1388 $g_settings['enableEmbedResizeHeight'] = 600;
1389 update_option(EMBEDPRESS_PLG_NAME, $g_settings);
1390 }
1391
1392 if (isset($g_settings[$key])) {
1393 return $g_settings[$key];
1394 }
1395
1396 return '';
1397 }
1398
1399
1400
1401 public static function get_branding_value($key, $provider)
1402 {
1403 $settings = get_option(EMBEDPRESS_PLG_NAME . ':' . $provider, []);
1404
1405 // Check if provider has custom branding enabled and the specific key set
1406 if (isset($settings['branding']) && $settings['branding'] === 'yes') {
1407 // If provider has custom logo, use it
1408 if (isset($settings[$key]) && !empty($settings[$key])) {
1409 return $settings[$key];
1410 }
1411
1412 // If branding is enabled but no custom logo, use global brand as fallback
1413 if ($key === 'logo_url') {
1414 $global_logo = self::get_global_brand_logo_url();
1415 if (!empty($global_logo)) {
1416 return $global_logo;
1417 }
1418 }
1419 }
1420
1421 return '';
1422 }
1423
1424 /**
1425 * Get global brand logo URL
1426 *
1427 * @return string
1428 */
1429 public static function get_global_brand_logo_url()
1430 {
1431 $global_brand_settings = get_option(EMBEDPRESS_PLG_NAME . ':global_brand', []);
1432 return isset($global_brand_settings['logo_url']) ? $global_brand_settings['logo_url'] : '';
1433 }
1434
1435 /**
1436 * Get global brand logo ID
1437 *
1438 * @return int
1439 */
1440 public static function get_global_brand_logo_id()
1441 {
1442 $global_brand_settings = get_option(EMBEDPRESS_PLG_NAME . ':global_brand', []);
1443 return isset($global_brand_settings['logo_id']) ? intval($global_brand_settings['logo_id']) : 0;
1444 }
1445
1446
1447 public static function format_number($number)
1448 {
1449 if ($number >= 1000000000) {
1450 return number_format($number / 1000000000, 1) . 'b';
1451 } elseif ($number >= 1000000) {
1452 return number_format($number / 1000000, 1) . 'm';
1453 } elseif ($number >= 1000) {
1454 return number_format($number / 1000, 1) . 'k';
1455 } else {
1456 return $number;
1457 }
1458 }
1459
1460 public static function get_id($item)
1461 {
1462 $vid = isset($item->snippet->resourceId->videoId) ? $item->snippet->resourceId->videoId : null;
1463 $vid = $vid ? $vid : (isset($item->id->videoId) ? $item->id->videoId : null);
1464 $vid = $vid ? $vid : (isset($item->id) ? $item->id : null);
1465 return $vid;
1466 }
1467
1468 public static function clean_api_error($raw_message)
1469 {
1470 return htmlspecialchars(strip_tags(preg_replace('@&key=[^& ]+@i', '&key=*******', $raw_message)));
1471 }
1472
1473 public static function clean_api_error_html($raw_message)
1474 {
1475 $clean_html = '';
1476 if ((defined('REST_REQUEST') && REST_REQUEST) || current_user_can('manage_options')) {
1477 $clean_html = '<div>' . __('EmbedPress: ', 'embedpress') . self::clean_api_error($raw_message) . '</div>';
1478 }
1479 return $clean_html;
1480 }
1481
1482 public static function get_thumbnail_url($item, $quality, $privacyStatus)
1483 {
1484 $url = "";
1485 if ($privacyStatus == 'private') {
1486 $url = EMBEDPRESS_URL_ASSETS . 'images/youtube/private.png';
1487 } elseif (isset($item->snippet->thumbnails->{$quality}->url)) {
1488 $url = $item->snippet->thumbnails->{$quality}->url;
1489 } elseif (isset($item->snippet->thumbnails->medium->url)) {
1490 $url = $item->snippet->thumbnails->medium->url;
1491 } elseif (isset($item->snippet->thumbnails->default->url)) {
1492 $url = $item->snippet->thumbnails->default->url;
1493 } elseif (isset($item->snippet->thumbnails->high->url)) {
1494 $url = $item->snippet->thumbnails->high->url;
1495 } else {
1496 $url = EMBEDPRESS_URL_ASSETS . 'images/youtube/deleted-video-thumb.png';
1497 }
1498 return $url;
1499 }
1500
1501 public static function compare_vid_date($a, $b)
1502 {
1503 $dateA = strtotime($a->snippet->publishedAt);
1504 $dateB = strtotime($b->snippet->publishedAt);
1505
1506 // Sort in descending order (newest first)
1507 return $dateB - $dateA;
1508 }
1509
1510
1511 public static function get_youtube_video_data($api_key, $video_id)
1512 {
1513 // Set a unique transient name based on the video ID
1514 $transient_name = 'youtube_video_data_' . $video_id;
1515
1516 // Try to get data from the transient cache
1517 $video_data = get_transient($transient_name);
1518
1519 // If no cached data, fetch from the API
1520 if ($video_data === false) {
1521 // YouTube Data API URL
1522 $url = "https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id={$video_id}&key={$api_key}";
1523
1524 // Fetch the data from the API
1525 $response = wp_remote_get($url);
1526
1527 if (is_wp_error($response)) {
1528 return false; // Return false if there is an error
1529 }
1530
1531 $body = wp_remote_retrieve_body($response);
1532 $video_data = json_decode($body, true);
1533
1534 if (isset($video_data['items'][0])) {
1535 $video_data = $video_data['items'][0];
1536
1537 // Cache the data in a transient for 12 hours
1538 set_transient($transient_name, $video_data, 24 * HOUR_IN_SECONDS);
1539 } else {
1540 return false; // Return false if no data found
1541 }
1542 }
1543
1544 return $video_data;
1545 }
1546
1547 public static function trimTitle($title, $wordCount)
1548 {
1549 $words = explode(' ', $title);
1550
1551 if (count($words) <= $wordCount) {
1552 return $title; // No trimming needed
1553 }
1554
1555 $trimmedWords = array_slice($words, 0, $wordCount);
1556
1557 return implode(' ', $trimmedWords) . ' ...';
1558 }
1559
1560 public static function timeAgo($datetime)
1561 {
1562 $now = new \DateTime();
1563 $date = new \DateTime($datetime);
1564 $interval = $now->diff($date);
1565
1566 if ($interval->y > 0) {
1567 return $interval->y . ' year' . ($interval->y > 1 ? 's' : '') . ' ago';
1568 } elseif ($interval->m > 0) {
1569 return $interval->m . ' month' . ($interval->m > 1 ? 's' : '') . ' ago';
1570 } elseif ($interval->d > 0) {
1571 return $interval->d . ' day' . ($interval->d > 1 ? 's' : '') . ' ago';
1572 } elseif ($interval->h > 0) {
1573 return $interval->h . ' hour' . ($interval->h > 1 ? 's' : '') . ' ago';
1574 } elseif ($interval->i > 0) {
1575 return $interval->i . ' minute' . ($interval->i > 1 ? 's' : '') . ' ago';
1576 } else {
1577 return 'just now';
1578 }
1579 }
1580
1581 public static function removeQuote($attributes)
1582 {
1583 $parsedAttributes = [];
1584
1585 $regex = '/^on.*/i';
1586
1587 foreach ($attributes as $key => $value) {
1588 if (is_string($value)) {
1589 $cleanValue = str_replace(['"', "'"], '', $value);
1590 } else {
1591 $cleanValue = $value;
1592 }
1593
1594 if (!preg_match($regex, $key)) {
1595 $parsedAttributes[$key] = $cleanValue;
1596 }
1597 }
1598
1599 return $parsedAttributes;
1600 }
1601
1602 public static function getBooleanParam($param, $default = false)
1603 {
1604 return isset($param) && is_string($param) && ($param == 'true' || $param == 'yes') ? 'true' : ($default ? 'true' : 'false');
1605 }
1606
1607 public static function has_allowed_roles($allowed_roles = [])
1608 {
1609
1610 if (empty($allowed_roles) || (count($allowed_roles) == 1 && empty($allowed_roles[0]))) {
1611 return true;
1612 }
1613 $current_user = wp_get_current_user();
1614 $user_roles = $current_user->roles;
1615
1616 return !empty(array_intersect($user_roles, $allowed_roles));
1617 }
1618
1619 public static function get_elementor_global_color($settings, $key)
1620 {
1621
1622 $global_color = $settings[$key];
1623
1624 if (isset($settings['__globals__'][$key])) {
1625 $color_setting = $settings['__globals__'][$key];
1626
1627 if (strpos($color_setting, 'globals/colors?id=') === 0) {
1628 // It's a global color reference
1629 $global_id = str_replace('globals/colors?id=', '', $color_setting);
1630
1631 $kit = Plugin::$instance->kits_manager->get_current_settings();
1632
1633 $system_colors = isset($kit['system_colors']) ? $kit['system_colors'] : [];
1634 $custom_colors = isset($kit['custom_colors']) ? $kit['custom_colors'] : [];
1635 $global_colors = array_merge($system_colors, $custom_colors);
1636
1637 foreach ($global_colors as $color) {
1638
1639 if ($color['_id'] === $global_id) {
1640 $global_color = $color['color']; // Found a match, set the color
1641 break;
1642 }
1643 }
1644 }
1645 }
1646 return $global_color;
1647 }
1648
1649 public static function get_provider_name($source_url)
1650 {
1651 if (self::is_youtube_channel($source_url)) {
1652 $source_name = 'YoutubeChannel';
1653 } else if (self::is_youtube($source_url)) {
1654 $source_name = 'Youtube';
1655 } else if (!empty(self::is_file_url($source_url))) {
1656 $source_name = 'document_' . self::get_extension_from_file_url($source_url);
1657 } else if (self::is_opensea($source_url)) {
1658 $source_name = 'OpenSea';
1659 } else {
1660 Shortcode::get_embera_instance();
1661 $collectios = Shortcode::get_collection();
1662 $provider = $collectios->findProviders($source_url);
1663
1664 if (!empty($provider[$source_url])) {
1665 $source_name = $provider[$source_url]->getProviderName();
1666 } else {
1667 $host = parse_url($source_url, PHP_URL_HOST);
1668 if ($host) {
1669 $parts = explode('.', $host);
1670 if (count($parts) > 1) {
1671 $source_name = $parts[1];
1672 } else {
1673 // Handle the case where the host doesn't have at least two parts
1674 $source_name = $host;
1675 }
1676 } else {
1677 // Handle the case where parse_url fails
1678 $source_name = '';
1679 }
1680 }
1681 }
1682
1683 return $source_name;
1684 }
1685
1686 public static function get_user_roles()
1687 {
1688 global $wp_roles; // Access global roles object
1689 $user_roles = [];
1690
1691 if (isset($wp_roles->roles) && is_array($wp_roles->roles)) {
1692 foreach ($wp_roles->roles as $role_key => $role_data) {
1693 $user_roles[] = [
1694 'value' => $role_key, // Machine-readable key
1695 'label' => $role_data['name'], // Human-readable name
1696 ];
1697 }
1698 }
1699
1700 return $user_roles;
1701 }
1702
1703 public static function has_content_allowed_roles($allowed_roles = [])
1704 {
1705 // Ensure it's always an array
1706 if (!is_array($allowed_roles)) {
1707 $allowed_roles = [];
1708 }
1709
1710 if (count($allowed_roles) === 1 && empty($allowed_roles[0])) {
1711 return true;
1712 }
1713
1714 $current_user = wp_get_current_user();
1715 $user_roles = $current_user->roles;
1716
1717 return !empty(array_intersect($user_roles, $allowed_roles));
1718 }
1719
1720
1721 }
1722