PluginProbe
Themify Builder / 7.7.0
Themify Builder v7.7.0
7.8.1 7.8.0 7.7.9 7.7.8 7.7.7 7.7.6 7.7.5 7.7.4 7.7.3 7.7.2 trunk 7.6.0 7.6.1 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.8 7.6.9 7.7.0 7.7.1
themify-builder / modules / module-widget.php

module-widget.php in Themify Builder 7.7.0, at modules/module-widget.php

343 lines 12.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 defined('ABSPATH') || exit;
4
5 /**
6 * Module Name: Widget
7 * Description: Display any available widgets
8 */
9 class TB_Widget_Module extends Themify_Builder_Component_Module {
10
11 public static function init():void {
12 add_action('wp_ajax_tb_get_widget_items', array(__CLASS__, 'get_items'));
13 add_action('wp_ajax_module_widget_get_form', array(__CLASS__, 'widget_get_form'), 10);
14 add_action('tb_data_before_save', array(__CLASS__, 'before_builder_save'), 10, 2);
15 }
16
17 public static function get_module_name():string {
18 return __('Widget', 'themify');
19 }
20
21 public static function get_items() {
22 $result = array();
23 global $wp_widget_factory;
24 if (!empty($wp_widget_factory->widgets)) {
25 foreach ($wp_widget_factory->widgets as $widget) {
26 $class = get_class($widget);
27 $result[$class] = array('n' => $widget->name, 'b' => $widget->id_base);
28 if (!empty($widget->widget_options['description'])) {
29 $result[$class]['d'] = $widget->widget_options['description'];
30 }
31 }
32 }
33
34 $columns = array_column($result, 'n');
35 array_multisort($columns, SORT_ASC, $result);
36
37 die(json_encode($result));
38 }
39
40 /**
41 * Get a widget's registered key in $wp_widget_factory from its classname.
42 * register_widget() works with WP_Widget instances too, in such cases the
43 * widget's key is a hashed string.
44 *
45 * @return string|null
46 */
47 public static function get_widget_factory_name($classname) {
48 if (empty($classname) || !class_exists($classname,false)) {
49 return;
50 }
51 global $wp_widget_factory;
52 if (isset($wp_widget_factory->widgets[$classname])) {
53 return $classname;
54 }
55 foreach ($wp_widget_factory->widgets as $key => $widget) {
56 if ($widget instanceof WP_Widget && get_class($widget) === $classname) {
57 return $key;
58 }
59 }
60 }
61
62 public static function widget_get_form() {
63 check_ajax_referer('tf_nonce', 'nonce');
64
65 global $wp_widget_factory;
66 require_once ABSPATH . 'wp-admin/includes/widgets.php';
67 $widget_class = $_POST['load_class'];
68 if ($widget_class == '') {
69 die(-1);
70 }
71 $widget_class = str_replace('\\\\', '\\', $widget_class);
72
73 try {
74 $instance = !empty($_POST['widget_instance']) && $_POST['widget_instance'] !== 'null' ? $_POST['widget_instance'] : array();
75 if ( is_string( $instance ) ) {
76 $instance = json_decode( stripslashes( $instance ), true );
77 }
78 } catch( Exception $e ) {
79 $instance = [];
80 }
81 $instance = TB_Widget_Module::sanitize_widget_instance($instance);
82
83 $widget_key = self::get_widget_factory_name($widget_class);
84 if (!$widget_key) {
85 die(-1);
86 }
87 $widget = $wp_widget_factory->widgets[$widget_key];
88
89 $widget->number = next_widget_id_number($_POST['id_base']);
90 ob_start();
91 $instance = stripslashes_deep($instance);
92 $template = '';
93 $src = array();
94
95 if (empty($_POST['tpl_loaded']) && method_exists($widget, 'render_control_template_scripts')) {
96 require_once ABSPATH . WPINC . '/media-template.php';
97 ob_start();
98 $widget->render_control_template_scripts();
99 if ($widget->id_base !== 'text') {
100 wp_print_media_templates();
101 }
102
103 $template = ob_get_contents();
104 ob_end_clean();
105 $widget->enqueue_admin_scripts();
106 $type = str_replace('_', '-', $widget->id_base) . '-widget';
107 if ($widget->id_base === 'text') {
108 $type .= 's';
109 }
110 wp_enqueue_script($type);
111 global $wp_scripts;
112 if (isset($wp_scripts->registered[$type])) {
113 $script = $wp_scripts->registered[$type];
114 if ($widget->id_base !== 'text' && !empty($wp_scripts->registered[$type]->deps)) {
115 foreach ($wp_scripts->registered[$type]->deps as $deps) {
116 $src[] = array('src' => self::resolve_script_path($wp_scripts->registered[$deps]->src));
117 }
118 }
119
120 $src[] = array('src' => self::resolve_script_path($script->src), 'extra' => !empty($script->extra) ? $script->extra : '');
121 }
122 }
123
124 /* prevent errors */
125 set_error_handler(function($errno, $errstr, $errfile, $errline) {
126 return false;
127 });
128 try{
129 @$widget->form($instance);
130 }
131 catch(Throwable $e){
132 }
133 restore_error_handler();
134
135 do_action('in_widget_form', $widget, null, $instance);
136 $form = ob_get_clean();
137 $base_name = 'widget-' . $widget->id_base . '\[' . $widget->number . '\]';
138 $form = preg_replace("/{$base_name}/", '', $form); // remove extra names
139 $form = str_replace(array(
140 '[',
141 ']'
142 ), '', $form); // remove extra [ & ] characters
143 $widget->form = $form;
144
145 /**
146 * The widget-id is not used to save widget data, it is however needed for compatibility
147 * with how core renders the module forms.
148 */
149 $form = '<div class="widget open">
150 <div class="widget-inside">
151 <div class="form">
152 <div class="widget-content">'
153 . $form .
154 '</div>
155 <input type="hidden" class="id_base" name="id_base" value="' . esc_attr($widget->id_base) . '" />
156 <input type="hidden" class="widget-id" name="widget-id" value="w_' . time() . '" />
157 <input type="hidden" class="widget-class" name="widget-class" value="' . $widget_class . '" />
158 </div>
159 </div>
160 <br/>
161 </div>';
162
163 global $wp_version;
164 wp_send_json(array(
165 'form' => $form,
166 'template' => $template,
167 'v' => $wp_version,
168 'src' => $src
169 ));
170 wp_die();
171 }
172
173 private static function resolve_script_path($src) {
174
175 $content_url = defined('WP_CONTENT_URL') ? WP_CONTENT_URL : '';
176
177 if (!preg_match('|^(https?:)?//|', $src) && !( $content_url && 0 === strpos($src, $content_url) )) {
178 if (!($guessurl = site_url() )) {
179 $guessurl = wp_guess_url();
180 }
181 $src = $guessurl . $src;
182 }
183
184 return $src;
185 }
186
187 /*
188 * Sanitize keys for widget fields
189 * This is required to provide backward compatibility with how widget data was saved.
190 *
191 * @return array
192 * @since 3.2.0
193 */
194
195 public static function sanitize_widget_instance($instance) {
196 if (is_array($instance)) {
197 foreach ($instance as $key => $val) {
198 preg_match('/.*\[\d\]\[(.*)\]/', $key, $matches);
199 if (isset($matches[1])) {
200 unset($instance[$key]);
201 $instance[$matches[1]] = $val;
202 }
203 }
204 }
205
206 return $instance;
207 }
208
209 /**
210 * Render plain content for static content.
211 *
212 * @param array $module
213 * @return string
214 */
215 public static function get_static_content(array $module):string {
216 if (!isset($module['mod_settings'])) {
217 return '';
218 }
219 return isset($module['mod_settings']['class_widget']) && 'Themify_Social_Links' === $module['mod_settings']['class_widget']?self::social_links_plain_content():parent::get_static_content($module);
220 }
221
222 private static function social_links_plain_content():string {
223 $out = '';
224 if (function_exists('themify_get_data')){
225 $data = themify_get_data();
226 $pre = 'setting-link_';
227
228 $field_ids = isset($data[$pre . 'field_ids']) ? json_decode($data[$pre . 'field_ids']) : false;
229
230 if (is_array($field_ids) || is_object($field_ids)) {
231 $out .= '<ul>';
232 $is_exist = function_exists('icl_t');
233 foreach ($field_ids as $fid) {
234
235 $title_name = $pre . 'title_' . $fid;
236
237 if ($is_exist) {
238 $title_val = icl_t('Themify', $title_name, $data[$title_name]);
239 } else {
240 $title_val = isset($data[$title_name]) ? $data[$title_name] : '';
241 }
242
243 $link_name = $pre . 'link_' . $fid;
244 $link_val = isset($data[$link_name]) ? trim($data[$link_name]) : '';
245 if ('' === $link_val) {
246 continue;
247 }
248 $out .= sprintf('<li><a href="%s">%s</a></li>', esc_url($link_val), $title_val);
249 }
250 $out .= '</ul>';
251 }
252 }
253 return $out;
254 }
255
256 /**
257 * Before Builder saves data, find all Widget modules and call
258 * WP_Widget::update() method on widget instance data.
259 *
260 * @return array
261 */
262 public static function before_builder_save(array $builder_data, $post_id) {
263 if (!empty($builder_data)) {
264 if (strpos(json_encode($builder_data), 'class_widget') !== false) {
265 foreach ($builder_data as $row_index => $row) {
266 if (!empty($row['cols'])) {
267 foreach ($row['cols'] as $col_index => $column) {
268 if (!empty($column['modules'])) {
269 foreach ($column['modules'] as $module_index => $module) {
270 if (!empty($module['cols'])) {
271 foreach ($module['cols'] as $sub_column_index => $sub_column) {
272 if (!empty($sub_column['modules'])) {
273 foreach ($sub_column['modules'] as $sub_module_index => $sub_module) {
274 if (isset($sub_module['mod_name']) && $sub_module['mod_name'] === 'widget') {
275 $builder_data[$row_index]['cols'][$col_index]['modules'][$module_index]['cols'][$sub_column_index]['modules'][$sub_module_index] = self::call_widget_update($sub_module);
276 }
277 }
278 }
279 }
280 }
281 if (isset($module['mod_name']) && $module['mod_name'] === 'widget') {
282 $builder_data[$row_index]['cols'][$col_index]['modules'][$module_index] = self::call_widget_update($module);
283 }
284 }
285 }
286 }
287 }
288 }
289 }
290 }
291 return $builder_data;
292 }
293
294 /**
295 * Takes a $module array, for "widget" modules will call WP_Widget::update() method
296 * on the widget instance data
297 *
298 * @return array
299 */
300 private static function call_widget_update($module) {
301 if (!empty($module['mod_settings']['instance_widget'])) {
302 global $wp_widget_factory;
303 $widget_class = $module['mod_settings']['class_widget'];
304 if (isset($wp_widget_factory->widgets[$widget_class])) {
305 set_error_handler(function($errno, $errstr, $errfile, $errline) {
306 return false;
307 });
308 try{
309 @$instance = $wp_widget_factory->widgets[$widget_class]->update($module['mod_settings']['instance_widget'], array());
310 /** documented in wp-includes/class-wp-widget.php */
311 @$instance = apply_filters( 'widget_update_callback', $instance, $module['mod_settings']['instance_widget'], $module['mod_settings']['instance_widget'], $wp_widget_factory->widgets[$widget_class] );
312 }
313 catch(Throwable $e){
314 }
315 restore_error_handler();
316
317 if (!isset($instance['widget-id']) && isset($module['mod_settings']['instance_widget']['widget-id'])) {
318 $instance['widget-id'] = $module['mod_settings']['instance_widget']['widget-id'];
319 }
320 $module['mod_settings']['instance_widget'] = $instance;
321 }
322 }
323 return $module;
324 }
325
326 public static function widget_gallery_lightbox($markup) {
327 return str_replace('<a', '<a class="themify_lightbox"', $markup);
328 }
329
330 public static function get_styling_image_fields() : array {
331 return [
332 'background_image' => '',
333 'b_i_w_t' => '.module .widgettitle'
334 ];
335 }
336
337 public static function get_translatable_text_fields( $module ) : array {
338 return [ 'mod_title_widget' ];
339 }
340 }
341
342 TB_Widget_Module::init();
343