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