PluginProbe
Juicer.io: Effortlessly embed, curate, and aggregate social media feeds into your website / trunk
Juicer.io: Effortlessly embed, curate, and aggregate social media feeds into your website vtrunk
1.12.18 1.12.5 1.12.6 1.12.7 1.12.8 1.12.9 1.2 1.3 1.3.1 1.4 1.4.1 1.5 1.6 1.6.1 1.7 1.7.1 1.7.2 1.8 1.9 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 All 45 releases
juicer / juicer.php

juicer.php in Juicer.io: Effortlessly embed, curate, and aggregate social media feeds into your website trunk, at juicer.php

346 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Juicer
4 * Plugin URI: https://wp.juicer.io
5 * Description: Embed, curate & aggregate social media feeds from Instagram, Twitter, TikTok, Facebook, LinkedIn, YouTube, Slack, etc. and customize them as you like.
6 * Version: 1.12.18
7 * Author: saas.group Inc.
8 * Author URI: https://saas.group
9 * License: GPLv2 or later
10 */
11
12 /*
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License
15 as published by the Free Software Foundation; either version 2
16 of the License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 */
27
28 define('JUICER_VERSION', '1.12.18');
29
30 class Juicer_Feed {
31 public function render($args) {
32 $defaults = array(
33 'name' => 'error',
34 );
35 $args = wp_parse_args($args, $defaults);
36 $name = $args['name'];
37
38 // Legacy backbone feeds load embed-no-jquery.js, which still references
39 // jQuery (the "nojquery" flag means "don't bundle it, use the page's
40 // jQuery"). Keep jQuery enqueued so themes that don't load it on every
41 // page still get it when the shortcode runs. Feed 2.0 doesn't need it
42 // but enqueueing is idempotent and other plugins/themes typically load
43 // jQuery anyway.
44 wp_enqueue_script('jquery');
45
46 // Output <div> + <script> inline at the shortcode position rather than
47 // enqueueing the embed script. wp_enqueue_script dedups by handle, so
48 // two shortcodes for the same feed name collide and the second
49 // invocation's attributes (e.g. filter=Instagram on the second segment)
50 // are dropped. Emitting the pair adjacently makes each shortcode
51 // self-contained and immune to handle collisions, footer placement,
52 // and optimization plugins that reorder enqueued scripts.
53 $map_attributes = generate_attributes($args);
54 $attributes = join('&', $map_attributes);
55
56 // Mirror args as data-* on the div so the embed JS can recover
57 // per-instance config even if a caching plugin moves the <script> tag.
58 $div_data_attrs = '';
59 foreach ($args as $key => $val) {
60 if ($key === 'name') continue;
61 $escaped_val = htmlspecialchars($val);
62 if ($escaped_val === '') continue;
63 $clean_key = str_replace('data-', '', $key);
64 $div_data_attrs .= ' data-' . esc_attr($clean_key) . '="' . esc_attr($val) . '"';
65 }
66
67 $script_url = '//www.juicer.io/embed/' . rawurlencode($name)
68 . '/wp-plugin-1-12.js?nojquery=true'
69 . ($attributes !== '' ? '&' . $attributes : '');
70
71 return sprintf(
72 '<div class="juicer-feed" data-feed-id="%s"%s></div>'
73 . '<script type="text/javascript" src="%s"></script>',
74 esc_attr($name),
75 $div_data_attrs,
76 esc_url($script_url)
77 );
78 }
79 }
80
81 function generate_attributes($array) {
82 $attrs = array();
83
84 foreach ($array as $key => $val) {
85 if ($key == 'name') {
86 continue;
87 }
88 $escaped_val = htmlspecialchars($val);
89 if (!empty($escaped_val)) {
90 if (strpos($key, "data-") !== false) {
91 $escaped_key = str_replace("data-", "", $key);
92 array_push($attrs, $escaped_key . '=' . $escaped_val);
93 } else {
94 array_push($attrs, $key . '=' . $escaped_val);
95 }
96 }
97 }
98
99 return $attrs;
100 }
101
102 function juicer_feed($args) {
103 $feed = new Juicer_Feed();
104 echo $feed->render($args);
105 }
106
107 function juicer_shortcode($args) {
108 extract(shortcode_atts(array(
109 'name' => 'error',
110 ), $args ));
111
112 $feed = new Juicer_Feed();
113 return $feed->render($args);
114 }
115 add_shortcode('juicer', 'juicer_shortcode');
116
117
118 function juicer_activate() {
119 // Only set cookie if headers haven't been sent
120 if (!headers_sent()) {
121 setcookie('juicer_welcome', 'true', time() + 3600, '/'); // Cookie expires in 1 hour
122 }
123 }
124 register_activation_hook(__FILE__, 'juicer_activate');
125
126 // Setup menu for admin section
127 function juicer_set_admin_menu() {
128 $hook_suffix = add_menu_page(
129 esc_html__('Juicer', 'juicer'),
130 esc_html__('Juicer', 'juicer'),
131 'manage_options',
132 'juicer-settings',
133 'juicer_set_settings_page',
134 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjIiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2MiA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQ4LjYwOTUgMTMuNDI4NUM1MS4wMDMzIDEzLjQyODUgNTIuOTMzOCAxMS40OTggNTIuOTMzOCA5LjEwNDIzVjYuMzI0MzJDNTIuODU2NiAzLjkzMDUxIDUxLjAwMzMgMi4wMDAwMiA0OC42MDk1IDIuMDAwMDJDNDYuMjE1NyAyLjAwMDAyIDQ0LjI4NTIgMy45MzA1MSA0NC4yODUyIDYuMzI0MzJWOS4xODE0NUM0NC4yODUyIDExLjQ5OCA0Ni4yMTU3IDEzLjQyODUgNDguNjA5NSAxMy40Mjg1WiIgZmlsbD0iIzlEQTJBNyIvPgo8cGF0aCBkPSJNNTIuODU2OSA0MS4yMjc1VjIzLjAwMzdDNTIuODU2OSAyMC44NDE1IDUwLjkyNjQgMTkuMTQyNyA0OC41MzI2IDE5LjE0MjdDNDYuMTM4OCAxOS4xNDI3IDQ0LjIwODMgMjAuOTE4OCA0NC4yMDgzIDIzLjAwMzdWMzMuNDI4M1YzNS41OTA1QzQ0LjIwODMgMzcuOTg0MyA0Mi4yNzc4IDM5LjkxNDggMzkuODg0IDM5LjkxNDhDMzcuNDkwMiAzOS45MTQ4IDM1LjYzNjkgMzcuOTg0MyAzNS41NTk3IDM1LjY2NzdWMzQuODk1NVYzNC4yMDA1SDM1LjQ4MjVDMzUuMzI4IDMyLjExNTYgMzMuNTUyIDMwLjU3MTIgMzEuNDY3MSAzMC41NzEyQzI5LjMwNDkgMzAuNTcxMiAyNy42MDYxIDMyLjExNTYgMjcuMjIgMzQuMTIzM0gyNy4xNDI4VjM0LjgxODNWMzcuNjc1NEMyNy4xNDI4IDQwLjA2OTIgMjUuMjEyMyA0MS45MjI1IDIyLjgxODUgNDEuOTIyNUMyMC40MjQ3IDQxLjkyMjUgMTguNDk0MiAzOS45OTIgMTguNDk0MiAzNy41OTgyVjMzLjM1MTFDMTMuMzk3NyAzMy4yNzM5IDEwIDM0LjQzMjIgMTAgNDEuMjI3NUMxMCA1Mi43MzMzIDE5LjU3NTIgNjEuOTk5NiAzMS40NjcxIDYxLjk5OTZDNDMuMjgxNyA2Mi4wNzY4IDUyLjg1NjkgNTIuNzMzMyA1Mi44NTY5IDQxLjIyNzVaIiBmaWxsPSIjOURBMkE3Ii8+CjxwYXRoIGQ9Ik0zMS40NjY5IDI0Ljg1N0MzMy44NjA3IDI0Ljg1NyAzNS43OTEyIDIyLjkyNjUgMzUuNzkxMiAyMC41MzI3VjE3LjY3NTVDMzUuNzkxMiAxNS4yODE3IDMzLjg2MDcgMTMuMzUxMiAzMS40NjY5IDEzLjM1MTJDMjkuMDczMSAxMy4zNTEyIDI3LjE0MjYgMTUuMjgxNyAyNy4xNDI2IDE3LjY3NTVWMjAuNTMyN0MyNy4xNDI2IDIyLjkyNjUgMjkuMDczMSAyNC44NTcgMzEuNDY2OSAyNC44NTdaIiBmaWxsPSIjOURBMkE3Ii8+CjxwYXRoIGQ9Ik0yMy41MTMxIDQyLjg0OTNDMjMuMzU4NyA0Mi41NDA1IDIzLjIwNDIgNDIuMzA4OCAyMy4wNDk4IDQxLjk5OTlDMjIuOTcyNiA0MS45OTk5IDIyLjk3MjYgNDEuOTk5OSAyMi44OTU0IDQxLjk5OTlDMjAuNTAxNSA0MS45OTk5IDE4LjU3MTEgNDAuMDY5NCAxOC41NzExIDM3LjY3NTZWMzMuNDI4NUMxNi4xNzcyIDMzLjM1MTMgMTQuMTY5NSAzMy41ODMgMTIuNzAyNCAzNC40MzI0QzEyLjM5MzUgMzUuNDM2MyAxMi4yMzkgMzYuNTk0NiAxMi4yMzkgMzguMDYxN0MxMi4yMzkgNDkuNTY3NSAyMS44MTQzIDU4LjgzMzggMzMuNzA2MSA1OC44MzM4QzM5LjM0MzEgNTguODMzOCA0NC41OTQxIDU3LjA1NzggNDguNDU1MSA1My44MTQ1QzQ5Ljk5OTUgNTEuODg0IDUxLjIzNSA0OS42NDQ3IDUyLjAwNzIgNDcuMTczNkM0My4wNDk3IDUzLjk2OSAyOS44NDUxIDUyLjg4NzkgMjMuNTEzMSA0Mi44NDkzWiIgZmlsbD0iIzlEQTJBNyIvPgo8cGF0aCBkPSJNMjEuMjc0MSA0NS45MzhDMTkuNDIwOCA0My4wMDM2IDE4Ljg4MDMgNDAuNjg3IDE4LjcyNTggMzguNzU2NUMxOC42NDg2IDM4LjQ0NzcgMTguNTcxNCAzOC4wNjE2IDE4LjU3MTQgMzcuNzUyN1YzMy41MDU2QzEzLjM5NzcgMzMuMjczOSAxMCAzNC41MDk1IDEwIDQxLjIyNzZDMTAgNTIuNzMzMyAxOS41NzUyIDYxLjk5OTcgMzEuNDY3MSA2MS45OTk3QzQxLjExOTUgNjEuOTk5NyA0OS4zMDQ4IDU1LjgyMjEgNTIuMDA3NSA0Ny4yNTA3QzQzLjEyNzIgNTYuMjg1NCAyOC4yMjM4IDU2Ljk4MDQgMjEuMjc0MSA0NS45MzhaIiBmaWxsPSIjOURBMkE3Ii8+Cjwvc3ZnPgo=',
135 99
136 );
137 }
138 add_action('admin_menu', 'juicer_set_admin_menu');
139
140 // Load custom admin CSS
141 function load_custom_wp_admin_style() {
142 wp_enqueue_style('juicer-admin-css', plugin_dir_url(__FILE__) . 'includes/admin/css/admin.css', array(), JUICER_VERSION);
143 }
144 add_action('admin_enqueue_scripts', 'load_custom_wp_admin_style');
145
146 // Load custom admin JavaScript and localize
147 function load_custom_wp_admin_script($hook_suffix) {
148 // Check if we're on the Juicer settings page or any admin page
149 if ($hook_suffix === 'toplevel_page_juicer-settings' || $hook_suffix === 'index.php') {
150 wp_enqueue_script('juicer-admin-js', plugin_dir_url(__FILE__) . 'includes/admin/js/admin.js', array('jquery'), JUICER_VERSION, true);
151
152 // Localize the script with your data
153 wp_localize_script('juicer-admin-js', 'juicer_admin', array(
154 'ajax_url' => admin_url('admin-ajax.php'),
155 'security' => wp_create_nonce('juicer_nonce')
156 ));
157 }
158 }
159 add_action('admin_enqueue_scripts', 'load_custom_wp_admin_script');
160
161
162 // Setup guide page
163 function juicer_set_settings_page() {
164 include('includes/admin/settings.php');
165 }
166
167 // Plugin setup guide link
168 function juicer_plugin_action_links($links) {
169 $links[] = '<a href="' . admin_url('admin.php?page=juicer-settings') . '">' . __('Setup guide') . '</a>';
170 return $links;
171 }
172 add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'juicer_plugin_action_links');
173
174 // Plugin review notice
175 // Check for feed existence and set option
176 function juicer_check_feed_existence() {
177 $host_url = home_url();
178 $response = wp_remote_get('https://www.juicer.io/api/hosts?hostname=' . $host_url);
179
180 // Default to no feeds existing
181 update_option('juicer_feed_exists', false);
182
183 if (!is_wp_error($response)) {
184 $response_code = wp_remote_retrieve_response_code($response);
185
186 if ($response_code !== 404) {
187 $body = wp_remote_retrieve_body($response);
188 $data = json_decode($body, true);
189
190 foreach ($data as $item) {
191 if (isset($item['feed_id'])) {
192 // Update the option to true as feed exists
193 update_option('juicer_feed_exists', true);
194 break;
195 }
196 }
197 }
198 }
199 }
200 add_action('admin_init', 'juicer_check_feed_existence');
201
202 // Display review notice
203 function juicer_review_notice() {
204 // Get the current screen object to check the hook suffix
205 $current_screen = get_current_screen();
206 $hook_suffix = $current_screen->base;
207
208 // Check if the current page is one of the allowed pages
209 if ($hook_suffix === 'toplevel_page_juicer-settings' || $hook_suffix === 'dashboard') {
210 if (get_option('juicer_feed_exists') && juicer_should_show_review_notice()) {
211 echo '<div class="notice notice-info is-dismissible" id="juicer-review-notice">';
212 echo '<div class="juicer__notice__holder">';
213 echo '<div class="juicer__notice__col_1">';
214 echo '<img src="' . plugin_dir_url(__FILE__) . 'includes/admin/img/juicer-icon.svg" width="24" >';
215 echo '</div>';
216 echo '<div class="juicer__notice__col_2">';
217 echo '<strong class="juicer__notice__title">Thanks for using Juicer!</strong>';
218 echo '<p class="juicer__notice__text">If you enjoy our plugin, would you consider leaving us a <strong>5-star review</strong> on Wordpress.org?</p>';
219 echo '<div class="juicer__notice__buttons">';
220 echo '<a href="https://wordpress.org/plugins/juicer/#reviews" target="_blank" id="juicer-love-it" class="button button-primary">Sure, I’d love to <img src="' . plugin_dir_url(__FILE__) . 'includes/admin/img/wp-outbound-link-icon-white.svg" width="16" height="16" ></a> ';
221 echo '<button id="juicer-maybe-later" class="juicer-notice__links">Maybe later</button> ';
222 echo '<button id="juicer-never-show" class="juicer-notice__links">Never show this again</button>';
223 echo '</div>';
224 echo '</div>';
225 echo '</div>';
226 echo '</div>';
227 }
228 }
229 }
230 add_action('admin_notices', 'juicer_review_notice');
231
232
233 // AJAX handler for dismissing the review notice
234 function juicer_dismiss_review_notice() {
235 check_ajax_referer('juicer_nonce', 'security');
236 if (current_user_can('manage_options')) {
237 if (isset($_POST['dismiss_type'])) {
238 $dismiss_type = sanitize_text_field($_POST['dismiss_type']);
239 if ($dismiss_type === 'permanent') {
240 // Never show again
241 update_option('juicer_review_permanently_dismissed', 'yes');
242 wp_send_json_success('Permanently dismissed.');
243 } elseif ($dismiss_type === 'temporary') {
244 // Dismiss for 7 days
245 update_option('juicer_review_dismissed', time() + 7 * DAY_IN_SECONDS);
246 wp_send_json_success('Temporarily dismissed.');
247 } else {
248 wp_send_json_error('Invalid dismiss type.');
249 }
250 } else {
251 wp_send_json_error('Dismiss type not set.');
252 }
253 } else {
254 wp_send_json_error('Permission denied.');
255 }
256 wp_die();
257 }
258 add_action('wp_ajax_juicer_dismiss_review_notice', 'juicer_dismiss_review_notice');
259
260 // Check if the review notice should be displayed
261 function juicer_should_show_review_notice() {
262 if (get_option('juicer_review_permanently_dismissed') === 'yes') {
263 return false;
264 }
265 $dismissed_until = get_option('juicer_review_dismissed');
266 if ($dismissed_until && time() < $dismissed_until) {
267 return false;
268 }
269 return true;
270 }
271
272 // Register the Elementor widget
273 function register_juicer_elementor_widget($widgets_manager) {
274 if (defined('ELEMENTOR_VERSION') && class_exists('Elementor\Widget_Base')) {
275 require_once plugin_dir_path(__FILE__) . 'includes/elementor/elementor-widget.php';
276 $widgets_manager->register(new \Elementor_Juicer_Widget());
277 }
278 }
279 add_action('elementor/widgets/register', 'register_juicer_elementor_widget');
280
281 // Enqueue custom CSS for Elementor editor
282 function enqueue_juicer_elementor_editor_styles() {
283 wp_enqueue_style(
284 'juicer-elementor-editor',
285 plugin_dir_url(__FILE__) . 'includes/elementor/juicer-elementor.css',
286 array(),
287 JUICER_VERSION
288 );
289 }
290 add_action('elementor/frontend/after_enqueue_styles', 'enqueue_juicer_elementor_editor_styles');
291 add_action('elementor/editor/after_enqueue_styles', 'enqueue_juicer_elementor_editor_styles');
292
293 function juicer_register_daterangepicker_assets() {
294 if (wp_script_is('daterangepicker', 'registered')) {
295 return;
296 }
297 wp_register_script('daterangepicker', 'https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js', array('jquery', 'moment'), '3.1', true);
298 wp_register_style('daterangepicker-css', 'https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css', array(), '3.1');
299 wp_register_script('juicer-daterangepicker-init', plugin_dir_url(__FILE__) . 'includes/elementor/daterangepicker-init.js', array('jquery', 'daterangepicker'), JUICER_VERSION, true);
300 }
301 add_action('elementor/editor/before_enqueue_scripts', 'juicer_register_daterangepicker_assets');
302 add_action('elementor/frontend/before_enqueue_scripts', 'juicer_register_daterangepicker_assets');
303
304 function juicer_editor_has_juicer_widget() {
305 if (!isset($_GET['post']) || !function_exists('\Elementor\Plugin::instance')) {
306 return false;
307 }
308 $post_id = absint($_GET['post']);
309 if (!$post_id) {
310 return false;
311 }
312 $document = \Elementor\Plugin::instance()->documents->get($post_id);
313 if (!$document) {
314 return false;
315 }
316 $data = $document->get_elements_data();
317 return juicer_find_widget_in_data($data, 'juicer_widget');
318 }
319
320 function juicer_find_widget_in_data($elements, $widget_type) {
321 if (!is_array($elements)) {
322 return false;
323 }
324 foreach ($elements as $element) {
325 if (isset($element['widgetType']) && $element['widgetType'] === $widget_type) {
326 return true;
327 }
328 if (!empty($element['elements']) && juicer_find_widget_in_data($element['elements'], $widget_type)) {
329 return true;
330 }
331 }
332 return false;
333 }
334
335 function juicer_enqueue_daterangepicker_in_editor() {
336 if (!juicer_editor_has_juicer_widget()) {
337 return;
338 }
339 wp_enqueue_script('moment');
340 wp_enqueue_script('daterangepicker');
341 wp_enqueue_style('daterangepicker-css');
342 wp_enqueue_script('juicer-daterangepicker-init');
343 }
344 add_action('elementor/editor/after_enqueue_scripts', 'juicer_enqueue_daterangepicker_in_editor');
345 ?>
346