PluginProbe ʕ •ᴥ•ʔ
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager / 3.32
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager v3.32
trunk 2.1.2.0 3.0.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.3 3.31 3.32 3.35 3.36 3.37 3.38
custom-sidebars / inc / external / wdev-frash / module.php
custom-sidebars / inc / external / wdev-frash Last commit date
README.md 10 years ago admin.css 9 years ago admin.js 10 years ago module.php 9 years ago
module.php
457 lines
1 <?php
2 /**
3 * WPMUDEV Frash - Free Dashboard Notification module.
4 * Used by wordpress.org hosted plugins.
5 *
6 * @version 1.1.0
7 * @author Incsub (Philipp Stracker)
8 */
9 if ( ! class_exists( 'WDev_Frash' ) ) {
10 class WDev_Frash {
11
12 /**
13 * List of all registered plugins.
14 *
15 * @since 1.0.0
16 * @var array
17 */
18 protected $plugins = array();
19
20 /**
21 * Module options that are stored in database.
22 * Timestamps are stored here.
23 *
24 * Note that this option is stored in site-meta for multisite installs.
25 *
26 * @since 1.0.0
27 * @var array
28 */
29 protected $stored = array();
30
31 /**
32 * Initializes and returns the singleton instance.
33 *
34 * @since 1.0.0
35 */
36 static public function instance() {
37 static $Inst = null;
38
39 if ( null === $Inst ) {
40 $Inst = new WDev_Frash();
41 }
42
43 return $Inst;
44 }
45
46 /**
47 * Set up the WDev_Frash module. Private singleton constructor.
48 *
49 * @since 1.0.0
50 */
51 private function __construct() {
52 $this->read_stored_data();
53
54 $this->add_action( 'wdev-register-plugin', 5 );
55 $this->add_action( 'load-index.php' );
56
57 $this->add_action( 'wp_ajax_frash_act' );
58 $this->add_action( 'wp_ajax_frash_dismiss' );
59 }
60
61 /**
62 * Load persistent module-data from the WP Database.
63 *
64 * @since 1.0.0
65 */
66 protected function read_stored_data() {
67 $data = get_site_option( 'wdev-frash', false, false );
68
69 if ( ! is_array( $data ) ) {
70 $data = array();
71 }
72
73 // A list of all plugins with timestamp of first registration.
74 if ( ! isset( $data['plugins'] ) || ! is_array( $data['plugins'] ) ) {
75 $data['plugins'] = array();
76 }
77
78 // A list with pending messages and earliest timestamp for display.
79 if ( ! isset( $data['queue'] ) || ! is_array( $data['queue'] ) ) {
80 $data['queue'] = array();
81 }
82
83 // A list with all messages that were handles already.
84 if ( ! isset( $data['done'] ) || ! is_array( $data['done'] ) ) {
85 $data['done'] = array();
86 }
87
88 $this->stored = $data;
89 }
90
91 /**
92 * Save persistent module-data to the WP database.
93 *
94 * @since 1.0.0
95 */
96 protected function store_data() {
97 update_site_option( 'wdev-frash', $this->stored );
98 }
99
100 /**
101 * Action handler for 'wdev-register-plugin'
102 * Register an active plugin.
103 *
104 * @since 1.0.0
105 * @param string $plugin_id WordPress plugin-ID (see: plugin_basename).
106 * @param string $title Plugin name for display.
107 * @param string $url_wp URL to the plugin on wp.org (domain not needed)
108 * @param string $cta_email Title of the Email CTA button.
109 * @param string $drip_plugin Optional. Plugin-param for the getdrip rule.
110 */
111 public function wdev_register_plugin( $plugin_id, $title, $url_wp, $cta_email = '', $drip_plugin = '' ) {
112 // Ignore incorrectly registered plugins to avoid errors later.
113 if ( empty( $plugin_id ) ) { return; }
114 if ( empty( $title ) ) { return; }
115 if ( empty( $url_wp ) ) { return; }
116
117 if ( false === strpos( $url_wp, '://' ) ) {
118 $url_wp = 'https://wordpress.org/' . trim( $url_wp, '/' );
119 }
120
121 $this->plugins[$plugin_id] = (object) array(
122 'id' => $plugin_id,
123 'title' => $title,
124 'url_wp' => $url_wp,
125 'cta_email' => $cta_email,
126 'drip_plugin' => $drip_plugin,
127 );
128
129 /*
130 * When the plugin is registered the first time we store some infos
131 * in the persistent module-data that help us later to find out
132 * if/which message should be displayed.
133 */
134 if ( empty( $this->stored['plugins'][$plugin_id] ) ) {
135 // First register the plugin permanently.
136 $this->stored['plugins'][$plugin_id] = time();
137
138 // Second schedule the messages to display.
139 $hash = md5( $plugin_id . '-email' );
140 $this->stored['queue'][$hash] = array(
141 'plugin' => $plugin_id,
142 'type' => 'email',
143 'show_at' => time(), // Earliest time to display note.
144 );
145
146 $hash = md5( $plugin_id . '-rate' );
147 $this->stored['queue'][$hash] = array(
148 'plugin' => $plugin_id,
149 'type' => 'rate',
150 'show_at' => time() + 7 * DAY_IN_SECONDS,
151 );
152
153 // Finally save the details.
154 $this->store_data();
155 }
156 }
157
158 /**
159 * Ajax handler called when the user chooses the CTA button.
160 *
161 * @since 1.0.0
162 */
163 public function wp_ajax_frash_act() {
164 $plugin = $_POST['plugin_id'];
165 $type = $_POST['type'];
166
167 $this->mark_as_done( $plugin, $type, 'ok' );
168
169 echo 1;
170 exit;
171 }
172
173 /**
174 * Ajax handler called when the user chooses the dismiss button.
175 *
176 * @since 1.0.0
177 */
178 public function wp_ajax_frash_dismiss() {
179 $plugin = $_POST['plugin_id'];
180 $type = $_POST['type'];
181
182 $this->mark_as_done( $plugin, $type, 'ignore' );
183
184 echo 1;
185 exit;
186 }
187
188 /**
189 * Action handler for 'load-index.php'
190 * Set-up the Dashboard notification.
191 *
192 * @since 1.0.0
193 */
194 public function load_index_php() {
195 if ( is_super_admin() ) {
196 $this->add_action( 'all_admin_notices' );
197 }
198 }
199
200 /**
201 * Action handler for 'admin_notices'
202 * Display the Dashboard notification.
203 *
204 * @since 1.0.0
205 */
206 public function all_admin_notices() {
207 $info = $this->choose_message();
208 if ( ! $info ) { return; }
209
210 $this->render_message( $info );
211 }
212
213 /**
214 * Check to see if there is a pending message to display and returns
215 * the message details if there is.
216 *
217 * Note that this function is only called on the main Dashboard screen
218 * and only when logged in as super-admin.
219 *
220 * @since 1.0.0
221 * @return object|false
222 * string $type [rate|email] Which message type?
223 * string $plugin WordPress plugin ID?
224 */
225 protected function choose_message() {
226 $obj = false;
227 $chosen = false;
228 $earliest = false;
229
230 $now = time();
231
232 // The "current" time can be changed via $_GET to test the module.
233 if ( defined( 'WP_DEBUG' ) && WP_DEBUG && ! empty( $_GET['time'] ) ) {
234 $custom_time = $_GET['time'];
235 if ( ' ' == $custom_time[0] ) { $custom_time[0] = '+'; }
236 if ( $custom_time ) { $now = strtotime( $custom_time ); }
237 if ( ! $now ) { $now = time(); }
238 }
239
240 $tomorrow = $now + DAY_IN_SECONDS;
241
242 foreach ( $this->stored['queue'] as $hash => $item ) {
243 $show_at = intval( $item['show_at'] );
244 $is_sticky = ! empty( $item['sticky'] );
245
246 if ( ! isset( $this->plugins[ $item['plugin'] ] ) ) {
247 // Deactivated plugin before the message was displayed.
248 continue;
249 }
250 $plugin = $this->plugins[ $item['plugin'] ];
251
252 $can_display = true;
253 if ( wp_is_mobile() ) {
254 // Do not display rating message on mobile devices.
255 if ( 'rate' == $item['type'] ) {
256 $can_display = false;
257 }
258 }
259 if ( 'email' == $item['type'] ) {
260 if ( ! $plugin->drip_plugin || ! $plugin->cta_email ) {
261 // Do not display email message with missing email params.
262 $can_display = false;
263 }
264 }
265 if ( $now < $show_at ) {
266 // Do not display messages that are not due yet.
267 $can_display = false;
268 }
269
270 if ( ! $can_display ) { continue; }
271
272 if ( $is_sticky ) {
273 // If sticky item is present then choose it!
274 $chosen = $hash;
275 break;
276 } elseif ( ! $earliest || $earliest < $show_at ) {
277 $earliest = $show_at;
278 $chosen = $hash;
279 // Don't use `break` because a sticky item might follow...
280 // Find the item with the earliest schedule.
281 }
282 }
283
284 if ( $chosen ) {
285 // Make the chosen item sticky.
286 $this->stored['queue'][$chosen]['sticky'] = true;
287
288 // Re-schedule other messages that are due today.
289 foreach ( $this->stored['queue'] as $hash => $item ) {
290 $show_at = intval( $item['show_at'] );
291
292 if ( empty( $item['sticky'] ) && $tomorrow > $show_at ) {
293 $this->stored['queue'][$hash]['show_at'] = $tomorrow;
294 }
295 }
296
297 // Save the changes.
298 $this->store_data();
299
300 $obj = (object) $this->stored['queue'][$chosen];
301 }
302
303 return $obj;
304 }
305
306 /**
307 * Moves a message from the queue to the done list.
308 *
309 * @since 1.0.0
310 * @param string $plugin Plugin ID.
311 * @param string $type [rate|email] Message type.
312 * @param string $state [ok|ignore] Button clicked.
313 */
314 protected function mark_as_done( $plugin, $type, $state ) {
315 $done_item = false;
316
317 foreach ( $this->stored['queue'] as $hash => $item ) {
318 unset( $this->stored['queue'][$hash]['sticky'] );
319
320 if ( $item['plugin'] == $plugin && $item['type'] == $type ) {
321 $done_item = $item;
322 unset( $this->stored['queue'][$hash] );
323 }
324 }
325
326 if ( $done_item ) {
327 $done_item['state'] = $state;
328 $done_item['hash'] = $hash;
329 $done_item['handled_at'] = time();
330 unset( $done_item['sticky'] );
331
332 $this->stored['done'][] = $done_item;
333 $this->store_data();
334 }
335 }
336
337 /**
338 * Renders the actual Notification message.
339 *
340 * @since 1.0.0
341 */
342 protected function render_message( $info ) {
343 $plugin = $this->plugins[$info->plugin];
344 $css_url = plugin_dir_url( __FILE__ ) . '/admin.css';
345 $js_url = plugin_dir_url( __FILE__ ) . '/admin.js';
346
347 ?>
348 <link rel="stylesheet" type="text/css" href="<?php echo esc_url( $css_url ); ?>" />
349 <div class="notice frash-notice frash-notice-<?php echo esc_attr( $info->type ); ?>" style="display:none">
350 <input type="hidden" name="type" value="<?php echo esc_attr( $info->type ); ?>" />
351 <input type="hidden" name="plugin_id" value="<?php echo esc_attr( $info->plugin ); ?>" />
352 <input type="hidden" name="url_wp" value="<?php echo esc_attr( $plugin->url_wp ); ?>" />
353 <input type="hidden" name="drip_plugin" value="<?php echo esc_attr( $plugin->drip_plugin ); ?>" />
354 <?php
355 if ( 'email' == $info->type ) {
356 $this->render_email_message( $plugin );
357 } elseif ( 'rate' == $info->type ) {
358 $this->render_rate_message( $plugin );
359 }
360 ?>
361 </div>
362 <script src="<?php echo esc_url( $js_url ); ?>"></script>
363 <?php
364 }
365
366 /**
367 * Output the contents of the email message.
368 * No return value. The code is directly output.
369 *
370 * @since 1.0.0
371 */
372 protected function render_email_message( $plugin ) {
373 $user = wp_get_current_user();
374 $user_name = $user->display_name;
375 $admin_email = get_site_option( 'admin_email' );
376
377 $msg = __( "We're happy that you've chosen to install %s! Are you interested in how to make the most of this plugin? How would you like a quick 5 day email crash course with actionable advice on building your membership site? Only the info you want, no subscription!", 'wdev_frash' );
378 $msg = apply_filters( 'wdev-email-message-' . $plugin->id, $msg );
379
380 ?>
381 <div class="frash-notice-logo"><span></span></div>
382 <div class="frash-notice-message">
383 <?php
384 printf(
385 $msg,
386 '<strong>' . $plugin->title . '</strong>'
387 );
388 ?>
389 </div>
390 <div class="frash-notice-cta">
391 <input type="email" name="email" value="<?php echo esc_attr( $admin_email ); ?>" />
392 <button class="frash-notice-act button-primary" data-msg="<?php _e( 'Thanks :)', 'wdev_frash' ); ?>">
393 <?php echo esc_html( $plugin->cta_email ); ?>
394 </button>
395 <button class="frash-notice-dismiss" data-msg="<?php _e( 'Saving', 'wdev_frash' ); ?>">
396 <?php _e( 'No thanks', 'wdev_frash' ); ?>
397 </button>
398 </div>
399 <?php
400 }
401
402 /**
403 * Output the contents of the rate-this-plugin message.
404 * No return value. The code is directly output.
405 *
406 * @since 1.0.0
407 */
408 protected function render_rate_message( $plugin ) {
409 $user = wp_get_current_user();
410 $user_name = $user->display_name;
411
412 $msg = __( "Hey %s, you've been using %s for a while now, and we hope you're happy with it.", 'wdev_frash' ) . '<br />'. __( "We've spent countless hours developing this free plugin for you, and we would really appreciate it if you dropped us a quick rating!", 'wdev_frash' );
413 $msg = apply_filters( 'wdev-rating-message-' . $plugin->id, $msg );
414
415 ?>
416 <div class="frash-notice-logo"><span></span></div>
417 <div class="frash-notice-message">
418 <?php
419 printf(
420 $msg,
421 '<strong>' . $user_name . '</strong>',
422 '<strong>' . $plugin->title . '</strong>'
423 );
424 ?>
425 </div>
426 <div class="frash-notice-cta">
427 <button class="frash-notice-act button-primary" data-msg="<?php _e( 'Thanks :)', 'wdev_frash' ); ?>">
428 <?php
429 printf(
430 __( 'Rate %s', 'wdev_frash' ),
431 esc_html( $plugin->title )
432 ); ?>
433 </button>
434 <button class="frash-notice-dismiss" data-msg="<?php _e( 'Saving', 'wdev_frash' ); ?>">
435 <?php _e( 'No thanks', 'wdev_frash' ); ?>
436 </button>
437 </div>
438 <?php
439 }
440
441 /**
442 * Registers a new action handler. The callback function has the same
443 * name as the action hook.
444 *
445 * @since 1.0.0
446 */
447 protected function add_action( $hook, $params = 1 ) {
448 $method_name = strtolower( $hook );
449 $method_name = preg_replace( '/[^a-z0-9]/', '_', $method_name );
450 $handler = array( $this, $method_name );
451 add_action( $hook, $handler, 5, $params );
452 }
453 }
454
455 // Initialize the module.
456 WDev_Frash::instance();
457 }