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