PluginProbe
WDesignKit – AI Templates, Widget Builder & MCP Workflow for WordPress / 2.6.5
WDesignKit – AI Templates, Widget Builder & MCP Workflow for WordPress v2.6.5
2.6.5 2.6.4 2.6.3 2.6.2 2.6.1 2.6.0 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5.0 2.4.0 2.3.3 2.3.2 2.3.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 All 127 releases
wdesignkit / wdesignkit.php

wdesignkit.php in WDesignKit – AI Templates, Widget Builder & MCP Workflow for WordPress 2.6.5, at wdesignkit.php

402 lines 16.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: WDesignKit - AI Templates, Widget Builder & MCP Workflow for WordPress
4 * Plugin URI: https://wdesignkit.com/
5 * Description: 3000+ Elementor & Gutenberg Templates, AI Templates, AI Widget Builder, AI Code Snippets, MCP Workflow, Cloud Workspace & 220+ Widgets Library.
6 * Version: 2.6.5
7 * Author: POSIMYTH
8 * Author URI: https://posimyth.com/
9 * Text Domain: wdesignkit
10 * Domain Path: /languages
11 * Requires PHP: 7.4
12 * License: GPLv3
13 * License URI: https://opensource.org/licenses/GPL-3.0
14 *
15 * @package wdesignkit
16 */
17
18 /** If this file is called directly, abort. */
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit;
21 }
22
23 if ( version_compare( PHP_VERSION, '7.4', '<' ) ) {
24 add_action(
25 'admin_notices',
26 function () {
27 echo '<div class="notice notice-error"><p>' .
28 sprintf(
29 /* translators: %s: minimum required PHP version */
30 esc_html__( 'WDesignKit requires PHP %s or higher. Please update PHP to use this plugin.', 'wdesignkit' ),
31 '7.4'
32 ) .
33 '</p></div>';
34 }
35 );
36 return;
37 }
38
39 define( 'WDKIT_VERSION', '2.6.5' );
40 define( 'WDKIT_FILE', __FILE__ );
41 define( 'WDKIT_PATH', plugin_dir_path( __FILE__ ) );
42 define( 'WDKIT_PBNAME', plugin_basename( __FILE__ ) );
43 define( 'WDKIT_BDNAME', basename( dirname( __FILE__ )) );
44 define( 'WDKIT_URL', plugins_url( '/', __FILE__ ) );
45 define( 'WDKIT_HOSTURL', site_url() );
46 define( 'WDKIT_INCLUDES', WDKIT_PATH . '/includes/' );
47 define( 'WDKIT_ASSETS', WDKIT_URL . 'assets/' );
48 define( 'WDKIT_TEXT_DOMAIN', 'wdesignkit' );
49 define( 'WDKIT_SERVER_SITE_URL', 'https://wdesignkit.com/' );
50 define( 'WDKIT_SERVER_API_URL', 'https://api.wdesignkit.com/' );
51 define( 'WDKIT_DOCUMENT', 'https://learn.wdesignkit.com/docs/' );
52
53 /** Widget Builder path*/
54 define( 'WDKIT_SERVER_PATH', wp_upload_dir()['baseurl'] . '/wdesignkit' );
55 define( 'WDKIT_BUILDER_PATH', wp_upload_dir()['basedir'] . '/wdesignkit' );
56 define( 'WDKIT_GET_SITE_URL', get_site_url() );
57
58 /*
59 * POSIMYTH Analytics SDK.
60 *
61 * Every POSIMYTH plugin bundles its own copy of the shared classes and registers it here rather than
62 * requiring them directly. The loader collects every registered copy and, at plugins_loaded priority
63 * 0 — before any consumer, which run at priority 10 — loads the files from the NEWEST one, as
64 * declared by that copy's version.php. Requiring them directly instead would let load order decide,
65 * and an older sibling would silently define the shared classes for the whole suite.
66 *
67 * Keep the copy in sync with .dev/sync-posimyth-sdk.py in Nexter Extension — never hand-edit
68 * anything under includes/posimyth-sdk/ except this product's own class-posimyth-tracker-wdk.php,
69 * which the sync script does not touch.
70 */
71 require_once WDKIT_PATH . 'includes/posimyth-sdk/posimyth-sdk-loader.php';
72 posimyth_sdk_register( WDKIT_PATH . 'includes/posimyth-sdk' );
73
74 /**
75 * Whether this install has been rebranded.
76 *
77 * Standalone rather than a method on the survey config class, because the tracker needs the same
78 * answer on front-end and cron requests, and that class carries eight inline reason icons that have
79 * no business being compiled outside the Plugins screen.
80 *
81 * Only the five rebranding keys count. Plain UI preferences stored in the same option must not
82 * suppress the tracker — that was the lesson from The Plus Addons, where they did.
83 *
84 * @since 2.6.4
85 *
86 * @return bool
87 */
88 function wdkit_posimyth_is_white_labelled() {
89 $label = get_option( 'wkit_white_label', array() );
90
91 if ( ! is_array( $label ) ) {
92 return false;
93 }
94
95 foreach ( array( 'plugin_name', 'plugin_desc', 'plugin_logo', 'developer_name', 'website_url' ) as $key ) {
96 if ( ! empty( $label[ $key ] ) && is_scalar( $label[ $key ] ) && '' !== trim( (string) $label[ $key ] ) ) {
97 return true;
98 }
99 }
100
101 return false;
102 }
103
104 add_action(
105 'plugins_loaded',
106 function () {
107 /*
108 * A rebranded install no longer bails here.
109 *
110 * It used to: the tracker, the consent notice and the posimyth_consent_wdk AJAX handler were
111 * all skipped, which meant the Settings panel's Data Sharing card had no handler to save to
112 * and had to be hidden entirely. Sharing now follows the white-label CRITERIA instead of the
113 * mere fact of rebranding — the feature stays available and consent-gated as everywhere else,
114 * while every user-visible string uses the reseller's own plugin name (see $wl_name below) and
115 * the POSIMYTH docs link is dropped wherever help_link is set.
116 *
117 * Consent still governs collection: on a rebranded site, as on any other, nothing is sent
118 * until someone turns the switch on.
119 */
120 $wl_label = get_option( 'wkit_white_label', array() );
121 $wl_label = is_array( $wl_label ) ? $wl_label : array();
122 $wl_name = ! empty( $wl_label['plugin_name'] ) && is_scalar( $wl_label['plugin_name'] ) ? trim( (string) $wl_label['plugin_name'] ) : '';
123 $wl_name = '' !== $wl_name ? $wl_name : 'WDesignKit';
124 // help_link is the reseller's "hide POSIMYTH documentation links" switch — honoured here the
125 // same way the editor stylesheets honour it.
126 $wl_hide_docs = ! empty( $wl_label['help_link'] );
127 // "Hide all Plugin Updates related News?" — the reseller's switch for plugin-authored admin
128 // notices. The consent bar is one, so it is not registered at all when this is on. The tracker
129 // and the Settings panel's Data Sharing card are unaffected: consent can still be given there,
130 // it is simply never asked for unprompted on a rebranded dashboard.
131 $wl_hide_notice = ! empty( $wl_label['plugin_news'] );
132
133 // Shared base already loaded by the SDK loader at priority 0; the subclass is ours alone.
134 require_once WDKIT_PATH . 'includes/posimyth-sdk/class-posimyth-tracker-wdk.php';
135
136 if ( class_exists( 'Posimyth_Tracker_WDK' ) ) {
137 /*
138 * Registers activate / deactivate / weekly-heartbeat hooks and the cron, all consent-gated,
139 * plus the template-import counter. NOT inside the is_admin() gate below: the weekly
140 * heartbeat fires from wp-cron.php, which is not an admin request.
141 */
142 Posimyth_Tracker_WDK::init();
143 }
144
145 if ( ! is_admin() ) {
146 return;
147 }
148
149 /*
150 * Guarded on class_exists rather than assumed: the loader requires the three shared files as a
151 * set, but a sibling plugin requiring one of them directly, or shipping an older SDK revision,
152 * can leave these classes undefined. An unguarded `new` would fatal on every admin page load.
153 */
154 // Also guarded on Posimyth_Tracker_WDK: this block reads its OPT_IN_OPTION constant and
155 // passes send_first_ping as a callback below. class-posimyth-tracker-wdk.php is required
156 // unconditionally above, but declaring the class can itself fail if a sibling POSIMYTH
157 // plugin's newer SDK copy won the loader with a diverged Posimyth_Tracker_Base signature —
158 // the exact multi-plugin case posimyth_sdk_register() exists for. Without this guard, that
159 // leaves Posimyth_Tracker_WDK undefined and the ::OPT_IN_OPTION reference below fatals every
160 // wp-admin request (Consent_Notice is only constructed when is_admin()), locking the admin
161 // out of the dashboard with no way to deactivate via the UI.
162 if ( class_exists( 'Posimyth_Consent_Notice' ) && class_exists( 'Posimyth_Tracker_WDK' ) ) {
163 /*
164 * WDesignKit's OWN consent key and OWN suite — not Nexter's.
165 *
166 * Nexter Extension and Nexter Blocks share one answer because they are one brand with one
167 * dashboard. WDesignKit is a separate product on its own site with its own dashboard, so it
168 * asks separately and stores separately. A site running both sees two notices, one per
169 * product — that is the intent, not a bug: consenting to share Nexter data is not consenting
170 * to share WDesignKit data.
171 *
172 * The constructor registers its own hooks; nothing else needs the instance.
173 */
174 $wdkit_consent_notice = new Posimyth_Consent_Notice(
175 array(
176 // The reseller's own product name on a rebranded install, 'WDesignKit' otherwise.
177 'plugin_name' => $wl_name,
178 'plugin_slug' => 'wdesignkit',
179 'opt_in_option' => Posimyth_Tracker_WDK::OPT_IN_OPTION,
180 'ajax_action' => 'posimyth_consent_wdk',
181 'installed_option' => 'posimyth_wdk_first_use_at',
182 'tracker_cb' => array( 'Posimyth_Tracker_WDK', 'send_first_ping' ),
183 // The SDK's suite_name default is 'Nexter', and it is what the notice prints instead
184 // of plugin_name once more than one product registers. WDesignKit is its own suite of
185 // one, so its suite name is simply its own name.
186 'suite_name' => $wl_name,
187 'suite_key' => 'wdk_suite',
188 // WDesignKit's own docs, not nexterwp.com. UTM matches the shape the SDK uses for its
189 // own default, so this notice is distinguishable from other places the docs are linked.
190 'docs_url' => WDKIT_DOCUMENT . 'data-sharing/?utm_source=wpbackend&utm_medium=admin&utm_campaign=datasharingnotice',
191 // Legacy hook only, for host stylesheets. The SDK stylesheet keys off `posi-*`.
192 'css_prefix' => 'wdkit',
193 // Passed explicitly. One copy of the notice class serves every active POSIMYTH plugin,
194 // so a product that passes nothing is painted by whatever that copy defaults to.
195 // --wdkit_blk_shade, matching the deactivation dialog. The SDK feeds this into
196 // --posi-accent, so the icon, left border and both buttons follow from this one value.
197 'accent' => '#020202',
198 )
199 );
200
201 /*
202 * "Hide all Plugin Updates related News?" is on: keep the object, drop only the banner.
203 *
204 * The notice is constructed either way because its constructor is what registers
205 * wp_ajax_posimyth_consent_wdk — the handler the Settings panel's Data Sharing toggle saves
206 * through. Skipping construction removed the banner AND broke that toggle on exactly this
207 * configuration. Unhooking render() suppresses the banner while leaving the handler live, so
208 * consent is never asked for unprompted but can still be given from Settings.
209 */
210 if ( $wl_hide_notice ) {
211 remove_action( 'admin_notices', array( $wdkit_consent_notice, 'render' ) );
212 }
213 }
214
215 /*
216 * Reseller has "hide documentation links" on: drop the notice's "See what's shared" anchor.
217 *
218 * Done in CSS rather than by passing an empty docs_url, because the SDK's render() prints the
219 * anchor unconditionally and would emit href="" — and includes/posimyth-sdk/ is sync-managed,
220 * so the notice class itself must not be edited here. Scoped to THIS product's notice, so a
221 * sibling POSIMYTH plugin's notice on the same screen keeps its own link.
222 *
223 * Hooked on the same handle the SDK attaches its own inline CSS to, at a later priority so
224 * this rule always follows and wins on equal specificity.
225 */
226 if ( $wl_hide_docs ) {
227 add_action(
228 'admin_enqueue_scripts',
229 function () {
230 wp_add_inline_style( 'wp-admin', '.posi-consent-notice.posi-consent--wdesignkit .posi-notice-text a { display: none; }' );
231 },
232 20
233 );
234 }
235
236 /*
237 * WDesignKit's skin for the shared deactivation dialog — design only.
238 *
239 * Enqueued from here, on the Plugins screen alone, because that is the only screen the dialog
240 * can open on. It overrides the SDK's base rules through `.posi-deact-p-wdesignkit`, the parent
241 * class that file documents for exactly this purpose, so includes/posimyth-sdk/ stays untouched
242 * and a sibling POSIMYTH product's dialog keeps its own look.
243 */
244 add_action(
245 'admin_enqueue_scripts',
246 function ( $hook ) {
247 if ( 'plugins.php' !== $hook ) {
248 return;
249 }
250
251 $skin_rel = 'assets/css/dashborad/wdkit-deactivate-survey.css';
252 $skin_abs = WDKIT_PATH . $skin_rel;
253
254 /*
255 * Versioned by mtime, not WDKIT_VERSION.
256 *
257 * WDKIT_VERSION only moves on release, so every edit to this file inside one version
258 * ships under a URL the browser already has cached — the stale copy keeps being served
259 * and the change looks like it did not apply. Falls back to the plugin version if the
260 * file is unreadable.
261 */
262 $skin_ver = file_exists( $skin_abs ) ? (string) filemtime( $skin_abs ) : WDKIT_VERSION;
263
264 wp_enqueue_style(
265 'wdkit-deactivate-survey',
266 WDKIT_URL . $skin_rel,
267 array(),
268 $skin_ver
269 );
270
271 /*
272 * Adds the dialog's close button. Injected rather than printed because the markup is
273 * sync-managed; see the file header. Versioned by mtime for the same reason as the
274 * stylesheet above.
275 */
276 $close_rel = 'assets/js/admin/wdkit-deactivate-survey.js';
277 $close_abs = WDKIT_PATH . $close_rel;
278 $close_ver = file_exists( $close_abs ) ? (string) filemtime( $close_abs ) : WDKIT_VERSION;
279
280 wp_enqueue_script(
281 'wdkit-deactivate-survey',
282 WDKIT_URL . $close_rel,
283 array(),
284 $close_ver,
285 true
286 );
287
288 wp_localize_script(
289 'wdkit-deactivate-survey',
290 'wdkitDeactSurvey',
291 array(
292 'close_label' => __( 'Close', 'wdesignkit' ),
293 )
294 );
295 }
296 );
297
298 if ( ! class_exists( 'Posimyth_Deactivation_Survey' ) ) {
299 return;
300 }
301
302 /*
303 * Required lazily, inside the is_admin() gate: the config carries eight inline reason icons
304 * that have no business being compiled on a front-end request.
305 */
306 require_once WDKIT_INCLUDES . 'admin/notices/class-wdkit-deactivate-survey.php';
307
308 new Posimyth_Deactivation_Survey( Wdkit_Deactivate_Survey::args() );
309 }
310 );
311
312 /**
313 * Developer tool: re-arm the data-sharing consent notice.
314 *
315 * The notice is deliberately hard to see twice — quiet for 2 days after install, snoozed 30 days by
316 * "Dismiss", silenced for good by "Allow", and never rendered while sharing is already on. That is
317 * right for users and leaves no way to review the bar again, so this resets those four gates.
318 *
319 * Three conditions, all required:
320 *
321 * - WP_DEBUG. This never loads on a production site, so it cannot be reached on a real install
322 * however the URL is guessed.
323 * - The same capability the notice itself answers for — network admin on multisite, since the
324 * consent is one answer per install.
325 * - A valid nonce. The reset writes site options, and a bare GET would let a crafted link flip
326 * another admin's consent state from anywhere on the web.
327 *
328 * Use the "Reset Data Sharing Notice" item added to the admin bar, which carries the nonce. There is
329 * deliberately no hand-typeable URL: that was the earlier QA shortcut this replaces.
330 *
331 * @since 2.6.4
332 */
333 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
334
335 add_action(
336 'admin_bar_menu',
337 function ( $bar ) {
338 $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
339
340 if ( ! current_user_can( $cap ) ) {
341 return;
342 }
343
344 $bar->add_node(
345 array(
346 'id' => 'wdkit-reset-consent',
347 'title' => __( 'Reset Data Sharing Notice', 'wdesignkit' ),
348 'href' => wp_nonce_url( admin_url( 'index.php?wdkit_reset_consent=1' ), 'wdkit_reset_consent' ),
349 'parent' => 'top-secondary',
350 )
351 );
352 },
353 100
354 );
355
356 add_action(
357 'admin_init',
358 function () {
359 if ( empty( $_GET['wdkit_reset_consent'] ) ) {
360 return;
361 }
362
363 $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
364
365 if ( ! current_user_can( $cap ) ) {
366 return;
367 }
368
369 check_admin_referer( 'wdkit_reset_consent' );
370
371 // Site options, matching how the SDK stores them: one consent per install, not per blog.
372 delete_site_option( 'posi_consent_dismissed_wdk_suite' );
373 delete_site_option( 'posi_consent_snoozed_until_wdk_suite' );
374 delete_site_option( 'posi_consent_grace_start_wdk_suite' );
375
376 // Sharing has to be off for the bar to render at all — the notice never asks for
377 // permission that has already been granted.
378 if ( class_exists( '\Posimyth_Tracker_WDK' ) ) {
379 update_site_option( \Posimyth_Tracker_WDK::OPT_IN_OPTION, 0 );
380 }
381
382 /*
383 * grace_period_ends() re-stamps the start it just found missing, so deleting that option is
384 * not enough on its own — the window has to be zeroed for THIS request too. admin_init runs
385 * before admin_notices, so the filter is in place before the notice decides.
386 */
387 add_filter( 'posimyth_consent_notice_grace_seconds', '__return_zero' );
388
389 add_action(
390 'admin_notices',
391 function () {
392 echo '<div class="notice notice-success is-dismissible"><p>' .
393 esc_html__( 'Data-sharing consent reset. The notice should appear below.', 'wdesignkit' ) .
394 '</p></div>';
395 },
396 5
397 );
398 }
399 );
400 }
401
402 require WDKIT_PATH . 'includes/class-wdkit-wdesignkit.php';