PluginProbe
Master Addons for Elementor – Elementor Addons, Widgets, Mega Menu Builder, Popup Builder, Widget Builder & Template Kits / 3.1.9
Master Addons for Elementor – Elementor Addons, Widgets, Mega Menu Builder, Popup Builder, Widget Builder & Template Kits v3.1.9
3.2.2 3.2.3 3.2.1 3.2.0 3.1.9 3.1.8 3.1.7 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.9 trunk 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.3 1.1.4 1.1.5 All 174 releases
master-addons / inc / admin / templates / widgets / class-widgets-downloader.php

class-widgets-downloader.php in Master Addons for Elementor – Elementor Addons, Widgets, Mega Menu Builder, Popup Builder, Widget Builder & Template Kits 3.1.9, at inc/admin/templates/widgets/class-widgets-downloader.php

190 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace MasterAddons\Inc\Admin\Templates\Widgets;
4
5 use MasterAddons\Inc\Admin\WidgetBuilder\Widget_Builder_Init;
6
7 defined('ABSPATH') || exit;
8
9 /**
10 * Installs a Widgets Library payload as a local jltma_widget post.
11 */
12 class Widgets_Downloader
13 {
14 const CATEGORY_SLUG = 'master-addons-widgets';
15 const CATEGORY_TITLE = 'Master Addons Widgets';
16
17 /**
18 * Required keys inside the payload's widget definition.
19 */
20 private static $required_widget_keys = ['title', 'html_code', 'css_code', 'js_code', 'sections'];
21
22 /**
23 * @param array $payload Decoded response from /masteraddons/v2/widget/{id}
24 * @return true|\WP_Error
25 */
26 public static function validate($payload)
27 {
28 if (!is_array($payload) || empty($payload['success'])) {
29 return new \WP_Error('bad_payload', __('The server did not return a valid widget.', 'master-addons'));
30 }
31
32 if (empty($payload['widget']) || !is_array($payload['widget'])) {
33 return new \WP_Error('bad_payload', __('The server did not return a valid widget.', 'master-addons'));
34 }
35
36 foreach (self::$required_widget_keys as $key) {
37 if (!array_key_exists($key, $payload['widget'])) {
38 return new \WP_Error(
39 'bad_payload',
40 // translators: %s is the missing JSON key.
41 sprintf(__('The widget payload is missing "%s".', 'master-addons'), $key)
42 );
43 }
44 }
45
46 return true;
47 }
48
49 /**
50 * Insert the widget. Every call creates a new post by design — a repeat
51 * download must never overwrite edits the user made locally.
52 *
53 * @param array $payload
54 * @return int|\WP_Error New jltma_widget post ID.
55 */
56 public static function install($payload)
57 {
58 $valid = self::validate($payload);
59 if (is_wp_error($valid)) {
60 return $valid;
61 }
62
63 $widget = $payload['widget'];
64 $title = !empty($payload['title']) ? $payload['title'] : $widget['title'];
65
66 $post_id = wp_insert_post([
67 'post_type' => 'jltma_widget',
68 'post_title' => self::unique_title($title),
69 'post_status' => 'publish',
70 ], true);
71
72 if (is_wp_error($post_id)) {
73 return $post_id;
74 }
75
76 self::register_category();
77
78 $data = [
79 'title' => $widget['title'],
80 'icon' => !empty($widget['icon']) ? $widget['icon'] : 'eicon-code',
81 'category' => self::CATEGORY_SLUG,
82 'html_code' => $widget['html_code'],
83 'css_code' => $widget['css_code'],
84 'js_code' => $widget['js_code'],
85 ];
86
87 update_post_meta($post_id, '_jltma_widget_data', $data);
88 update_post_meta($post_id, '_jltma_widget_sections', is_array($widget['sections']) ? $widget['sections'] : []);
89 update_post_meta($post_id, '_jltma_widget_category', self::CATEGORY_SLUG);
90
91 // External CSS/JS libraries are premium-only, same gate the Widget
92 // Builder's own save path uses: free builds store an empty set.
93 if (!empty($widget['includes']) && is_array($widget['includes'])) {
94 $includes = apply_filters(
95 'master_addons/widget_builder/persist_includes',
96 Widget_Builder_Init::normalize_includes(null),
97 Widget_Builder_Init::normalize_includes($widget['includes']),
98 $widget
99 );
100
101 update_post_meta(
102 $post_id,
103 '_jltma_widget_includes',
104 Widget_Builder_Init::normalize_includes($includes)
105 );
106 }
107 if (!empty($widget['dependencies']) && is_array($widget['dependencies'])) {
108 update_post_meta($post_id, '_jltma_widget_dependencies', $widget['dependencies']);
109 }
110 if (!empty($widget['conditions']) && is_array($widget['conditions'])) {
111 update_post_meta($post_id, '_jltma_widget_conditions', $widget['conditions']);
112 }
113
114 update_post_meta($post_id, '_jltma_library_source_id', absint($payload['widget_id'] ?? 0));
115 update_post_meta($post_id, '_jltma_library_downloaded_at', time());
116
117 if (!empty($payload['thumbnail'])) {
118 // Kept even after a successful sideload so the widgets list can
119 // re-fetch the image if the attachment is later deleted.
120 update_post_meta($post_id, '_jltma_library_thumbnail', esc_url_raw($payload['thumbnail']));
121 self::attach_thumbnail($post_id, $payload['thumbnail'], $title);
122 }
123
124 return $post_id;
125 }
126
127 /**
128 * Duplicates are permitted, so disambiguate the title instead of blocking.
129 */
130 private static function unique_title($title)
131 {
132 global $wpdb;
133
134 $existing = $wpdb->get_col($wpdb->prepare(
135 "SELECT post_title FROM {$wpdb->posts} WHERE post_type = 'jltma_widget' AND post_status != 'trash' AND (post_title = %s OR post_title LIKE %s)",
136 $title,
137 $wpdb->esc_like($title . ' (') . '%'
138 ));
139
140 if (empty($existing) || !in_array($title, $existing, true)) {
141 return $title;
142 }
143
144 $suffix = 2;
145 while (in_array($title . ' (' . $suffix . ')', $existing, true)) {
146 $suffix++;
147 }
148
149 return $title . ' (' . $suffix . ')';
150 }
151
152 /**
153 * Make sure the Elementor category exists in the option the widget
154 * builder reads when registering custom categories.
155 */
156 private static function register_category()
157 {
158 $categories = get_option('jltma_custom_widget_categories', []);
159 if (!is_array($categories)) {
160 $categories = [];
161 }
162
163 if (!isset($categories[self::CATEGORY_SLUG])) {
164 $categories[self::CATEGORY_SLUG] = self::CATEGORY_TITLE;
165 update_option('jltma_custom_widget_categories', $categories);
166 }
167 }
168
169 /**
170 * Sideload the catalog thumbnail. Failure is non-fatal — the widgets list
171 * column falls back to the icon glyph.
172 */
173 private static function attach_thumbnail($post_id, $url, $title)
174 {
175 if (!function_exists('media_sideload_image')) {
176 require_once ABSPATH . 'wp-admin/includes/media.php';
177 require_once ABSPATH . 'wp-admin/includes/file.php';
178 require_once ABSPATH . 'wp-admin/includes/image.php';
179 }
180
181 $attachment_id = media_sideload_image($url, $post_id, $title, 'id');
182
183 if (is_wp_error($attachment_id)) {
184 return;
185 }
186
187 set_post_thumbnail($post_id, $attachment_id);
188 }
189 }
190