PluginProbe ʕ •ᴥ•ʔ
Widget Options – Advanced Conditional Visibility for Gutenberg Blocks & Classic Widgets / 4.2.4
Widget Options – Advanced Conditional Visibility for Gutenberg Blocks & Classic Widgets v4.2.4
4.2.5 4.2.4 trunk 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.2 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8 3.8.1 3.8.10 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.8.8 3.8.9 3.8.9.1 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.5.1 4.0.6 4.0.6.1 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.2.0 4.2.1 4.2.2 4.2.3
widget-options / includes / snippets / class-snippets-api.php
widget-options / includes / snippets Last commit date
class-snippets-admin.php 1 month ago class-snippets-api.php 1 month ago class-snippets-cpt.php 1 month ago class-snippets-migration.php 1 month ago
class-snippets-api.php
259 lines
1 <?php
2 /**
3 * Display Logic Snippets - API
4 *
5 * Provides AJAX endpoints and helper functions for accessing snippets
6 * from various editors (widgets, Gutenberg, Elementor, etc.)
7 *
8 * @copyright Copyright (c) 2024, Widget Options Team
9 * @since 5.1
10 */
11
12 // Exit if accessed directly
13 if (!defined('ABSPATH')) exit;
14
15 /**
16 * Class WidgetOpts_Snippets_API
17 *
18 * Handles API endpoints and data retrieval for snippets
19 */
20 class WidgetOpts_Snippets_API {
21
22 /**
23 * Initialize the API
24 */
25 public static function init() {
26 // AJAX endpoints
27 add_action('wp_ajax_widgetopts_get_snippets', array(__CLASS__, 'ajax_get_snippets'));
28
29 // Localize script data
30 add_action('admin_enqueue_scripts', array(__CLASS__, 'localize_snippets_data'));
31 }
32
33 /**
34 * AJAX handler to get all snippets
35 */
36 public static function ajax_get_snippets() {
37 // Check if user can edit widgets
38 if (!current_user_can('edit_theme_options')) {
39 wp_send_json_error(array('message' => __('Permission denied.', 'widget-options')));
40 }
41
42 $snippets = WidgetOpts_Snippets_CPT::get_all_snippets();
43
44 // Format for Select2 / dropdown
45 $formatted = array(
46 array(
47 'id' => '',
48 'text' => __('— No Logic —', 'widget-options'),
49 )
50 );
51
52 foreach ($snippets as $snippet) {
53 $formatted[] = array(
54 'id' => $snippet['id'],
55 'text' => $snippet['title'],
56 'description' => $snippet['description'],
57 );
58 }
59
60 wp_send_json_success($formatted);
61 }
62
63 /**
64 * Localize snippets data for JavaScript
65 */
66 public static function localize_snippets_data($hook) {
67 // Only on widgets page and customizer
68 if (!in_array($hook, array('widgets.php', 'customize.php', 'post.php', 'post-new.php'))) {
69 return;
70 }
71
72 $snippets = WidgetOpts_Snippets_CPT::get_all_snippets();
73
74 $formatted = array(
75 array(
76 'id' => '',
77 'title' => __('— No Logic —', 'widget-options'),
78 'description' => '',
79 )
80 );
81
82 foreach ($snippets as $snippet) {
83 $formatted[] = array(
84 'id' => $snippet['id'],
85 'title' => $snippet['title'],
86 'description' => $snippet['description'],
87 );
88 }
89
90 wp_localize_script('jquery', 'widgetoptsSnippets', array(
91 'snippets' => $formatted,
92 'nonce' => wp_create_nonce('widgetopts_snippets'),
93 'strings' => array(
94 'selectSnippet' => __('Select Logic Snippet', 'widget-options'),
95 'noLogic' => __('— No Logic —', 'widget-options'),
96 'search' => __('Search snippets...', 'widget-options'),
97 ),
98 ));
99 }
100
101 /**
102 * Get snippets for dropdown (non-AJAX)
103 *
104 * @return array Array of snippets formatted for dropdown
105 */
106 public static function get_snippets_for_dropdown() {
107 $snippets = WidgetOpts_Snippets_CPT::get_all_snippets();
108
109 $options = array(
110 '' => __('— No Logic —', 'widget-options'),
111 );
112
113 foreach ($snippets as $snippet) {
114 $options[$snippet['id']] = $snippet['title'];
115 }
116
117 return $options;
118 }
119
120 /**
121 * Execute snippet logic by ID
122 *
123 * @param int $snippet_id Snippet post ID
124 * @return bool|null True to show, false to hide, null if snippet not found
125 */
126 public static function execute_snippet($snippet_id) {
127 if (empty($snippet_id)) {
128 return null;
129 }
130
131 $code = WidgetOpts_Snippets_CPT::get_snippet_code($snippet_id);
132
133 if ($code === false) {
134 return null;
135 }
136
137 // Apply legacy filters for backward compatibility
138 $code = apply_filters('widget_options_logic_override', $code);
139 $code = apply_filters('extended_widget_options_logic_override', $code);
140
141 // Handle filter returns
142 if ($code === false) {
143 return false;
144 }
145 if ($code === true) {
146 return true;
147 }
148
149 // Decode and execute
150 $code = htmlspecialchars_decode($code, ENT_QUOTES);
151
152 if (function_exists('widgetopts_safe_eval_trusted')) {
153 return widgetopts_safe_eval_trusted($code);
154 }
155 if (function_exists('widgetopts_safe_eval')) {
156 return widgetopts_safe_eval($code);
157 }
158
159 return null;
160 }
161
162 /**
163 * Get snippet ID from widget options (with backward compatibility)
164 *
165 * Checks for new snippet_id field, falls back to legacy logic field
166 *
167 * @param array $opts Widget options array
168 * @param string $editor Editor type (classic, elementor, beaver, siteorigin)
169 * @return int|string|null Snippet ID, legacy code, or null
170 */
171 public static function get_logic_from_opts($opts, $editor = 'classic') {
172 switch ($editor) {
173 case 'elementor':
174 // New format
175 if (isset($opts['widgetopts_logic_snippet_id']) && !empty($opts['widgetopts_logic_snippet_id'])) {
176 return array('type' => 'snippet', 'value' => $opts['widgetopts_logic_snippet_id']);
177 }
178 // Legacy format (should not exist after migration, but keep for safety)
179 if (isset($opts['widgetopts_logic']) && !empty($opts['widgetopts_logic'])) {
180 return array('type' => 'legacy', 'value' => $opts['widgetopts_logic']);
181 }
182 break;
183
184 case 'beaver':
185 // New format
186 if (isset($opts->widgetopts_logic_snippet_id) && !empty($opts->widgetopts_logic_snippet_id)) {
187 return array('type' => 'snippet', 'value' => $opts->widgetopts_logic_snippet_id);
188 }
189 // Legacy format
190 if (isset($opts->widgetopts_settings_logic) && !empty($opts->widgetopts_settings_logic)) {
191 return array('type' => 'legacy', 'value' => $opts->widgetopts_settings_logic);
192 }
193 break;
194
195 case 'siteorigin':
196 case 'classic':
197 default:
198 // New format
199 if (isset($opts['class']['logic_snippet_id']) && !empty($opts['class']['logic_snippet_id'])) {
200 return array('type' => 'snippet', 'value' => $opts['class']['logic_snippet_id']);
201 }
202 // Legacy format
203 if (isset($opts['class']['logic']) && !empty($opts['class']['logic'])) {
204 return array('type' => 'legacy', 'value' => $opts['class']['logic']);
205 }
206 break;
207 }
208
209 return null;
210 }
211
212 /**
213 * Process display logic and return visibility
214 *
215 * @param array|object $opts Widget options
216 * @param string $editor Editor type
217 * @return bool|null True to show, false to hide, null if no logic
218 */
219 public static function process_display_logic($opts, $editor = 'classic') {
220 $logic = self::get_logic_from_opts($opts, $editor);
221
222 if ($logic === null) {
223 return null; // No logic defined
224 }
225
226 if ($logic['type'] === 'snippet') {
227 return self::execute_snippet($logic['value']);
228 }
229
230 // Legacy code execution (for backward compatibility during transition)
231 if ($logic['type'] === 'legacy') {
232 $code = stripslashes(trim($logic['value']));
233 $code = apply_filters('widget_options_logic_override', $code);
234 $code = apply_filters('extended_widget_options_logic_override', $code);
235
236 if ($code === false) {
237 return false;
238 }
239 if ($code === true) {
240 return true;
241 }
242
243 $code = htmlspecialchars_decode($code, ENT_QUOTES);
244
245 if (function_exists('widgetopts_safe_eval_trusted')) {
246 return widgetopts_safe_eval_trusted($code);
247 }
248 if (function_exists('widgetopts_safe_eval')) {
249 return widgetopts_safe_eval($code);
250 }
251 }
252
253 return null;
254 }
255 }
256
257 // Initialize
258 WidgetOpts_Snippets_API::init();
259