PluginProbe ʕ •ᴥ•ʔ
Widget Options – Advanced Conditional Visibility for Gutenberg Blocks & Classic Widgets / 4.2.0
Widget Options – Advanced Conditional Visibility for Gutenberg Blocks & Classic Widgets v4.2.0
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 3 months ago class-snippets-api.php 3 months ago class-snippets-cpt.php 3 months ago class-snippets-migration.php 3 months ago
class-snippets-api.php
254 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 // Use the existing safe_eval function
153 if (function_exists('widgetopts_safe_eval')) {
154 return widgetopts_safe_eval($code);
155 }
156
157 return null;
158 }
159
160 /**
161 * Get snippet ID from widget options (with backward compatibility)
162 *
163 * Checks for new snippet_id field, falls back to legacy logic field
164 *
165 * @param array $opts Widget options array
166 * @param string $editor Editor type (classic, elementor, beaver, siteorigin)
167 * @return int|string|null Snippet ID, legacy code, or null
168 */
169 public static function get_logic_from_opts($opts, $editor = 'classic') {
170 switch ($editor) {
171 case 'elementor':
172 // New format
173 if (isset($opts['widgetopts_logic_snippet_id']) && !empty($opts['widgetopts_logic_snippet_id'])) {
174 return array('type' => 'snippet', 'value' => $opts['widgetopts_logic_snippet_id']);
175 }
176 // Legacy format (should not exist after migration, but keep for safety)
177 if (isset($opts['widgetopts_logic']) && !empty($opts['widgetopts_logic'])) {
178 return array('type' => 'legacy', 'value' => $opts['widgetopts_logic']);
179 }
180 break;
181
182 case 'beaver':
183 // New format
184 if (isset($opts->widgetopts_logic_snippet_id) && !empty($opts->widgetopts_logic_snippet_id)) {
185 return array('type' => 'snippet', 'value' => $opts->widgetopts_logic_snippet_id);
186 }
187 // Legacy format
188 if (isset($opts->widgetopts_settings_logic) && !empty($opts->widgetopts_settings_logic)) {
189 return array('type' => 'legacy', 'value' => $opts->widgetopts_settings_logic);
190 }
191 break;
192
193 case 'siteorigin':
194 case 'classic':
195 default:
196 // New format
197 if (isset($opts['class']['logic_snippet_id']) && !empty($opts['class']['logic_snippet_id'])) {
198 return array('type' => 'snippet', 'value' => $opts['class']['logic_snippet_id']);
199 }
200 // Legacy format
201 if (isset($opts['class']['logic']) && !empty($opts['class']['logic'])) {
202 return array('type' => 'legacy', 'value' => $opts['class']['logic']);
203 }
204 break;
205 }
206
207 return null;
208 }
209
210 /**
211 * Process display logic and return visibility
212 *
213 * @param array|object $opts Widget options
214 * @param string $editor Editor type
215 * @return bool|null True to show, false to hide, null if no logic
216 */
217 public static function process_display_logic($opts, $editor = 'classic') {
218 $logic = self::get_logic_from_opts($opts, $editor);
219
220 if ($logic === null) {
221 return null; // No logic defined
222 }
223
224 if ($logic['type'] === 'snippet') {
225 return self::execute_snippet($logic['value']);
226 }
227
228 // Legacy code execution (for backward compatibility during transition)
229 if ($logic['type'] === 'legacy') {
230 $code = stripslashes(trim($logic['value']));
231 $code = apply_filters('widget_options_logic_override', $code);
232 $code = apply_filters('extended_widget_options_logic_override', $code);
233
234 if ($code === false) {
235 return false;
236 }
237 if ($code === true) {
238 return true;
239 }
240
241 $code = htmlspecialchars_decode($code, ENT_QUOTES);
242
243 if (function_exists('widgetopts_safe_eval')) {
244 return widgetopts_safe_eval($code);
245 }
246 }
247
248 return null;
249 }
250 }
251
252 // Initialize
253 WidgetOpts_Snippets_API::init();
254