PluginProbe ʕ •ᴥ•ʔ
Hustle – Email Marketing, Lead Generation, Optins, Popups / 7.4.11
Hustle – Email Marketing, Lead Generation, Optins, Popups v7.4.11
7.8.13 7.8.13.1 trunk 3.0 3.1 3.1.1 3.1.2 3.1.3 3.1.4 4.3.2 4.4.4 4.4.5 4.4.5.1 4.4.5.4 4.6 4.6.1.1 4.6.1.4 4.7.0.2 4.7.0.3 4.7.0.7 4.7.0.9 4.7.1.0 4.7.1.1 4.8.0.0 5.0.0 5.0.1 5.0.1.1 5.0.1.2 5.1 5.1.1 5.1.2 5.1.3 5.1.3.1 5.1.3.2 5.1.4 5.1.5 6.0 6.0.1 6.0.2 6.0.3 6.0.4.2 6.0.5 6.0.6.1 6.0.7 6.0.8.1 6.0.9 7.0.0.1 7.0.2 7.0.3 7.0.4 7.1.0 7.1.1 7.2.0 7.2.1 7.3.0 7.3.1 7.3.3 7.3.5 7.3.6 7.3.7 7.4.0 7.4.1 7.4.11 7.4.13 7.4.13.1 7.4.2 7.4.3 7.4.4 7.4.5 7.4.5.1 7.4.5.2 7.4.6 7.4.7 7.5.0 7.6.0 7.6.1 7.6.3 7.6.4 7.6.6 7.7.0 7.7.1 7.8.0 7.8.1 7.8.10 7.8.10.1 7.8.10.2 7.8.11 7.8.12 7.8.12.1 7.8.2 7.8.3 7.8.4 7.8.5 7.8.6 7.8.7 7.8.8 7.8.9 7.8.9.1 7.8.9.2 7.8.9.3
wordpress-popup / lib / free-dashboard / module.php
wordpress-popup / lib / free-dashboard Last commit date
README.md 5 years ago admin.css 5 years ago admin.js 5 years ago module.php 5 years ago
module.php
468 lines
1 <?php
2 /**
3 * WPMUDEV Frash - Free Dashboard Notification module.
4 * Used by wordpress.org hosted plugins.
5 *
6 * @version 1.2
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 * User id /API Key for Mailchimp subscriber list
33 *
34 * @since 1.2
35 *
36 * @var string
37 *
38 */
39 private $mc_user_id = '53a1e972a043d1264ed082a5b';
40
41 /**
42 * Initializes and returns the singleton instance.
43 *
44 * @since 1.0.0
45 */
46 static public function instance() {
47 static $Inst = null;
48
49 if ( null === $Inst ) {
50 $Inst = new WDev_Frash();
51 }
52
53 return $Inst;
54 }
55
56 /**
57 * Set up the WDev_Frash module. Private singleton constructor.
58 *
59 * @since 1.0.0
60 */
61 private function __construct() {
62 $this->read_stored_data();
63
64 $this->add_action( 'wdev-register-plugin', 5 );
65 $this->add_action( 'load-index.php' );
66
67 $this->add_action( 'wp_ajax_frash_act' );
68 $this->add_action( 'wp_ajax_frash_dismiss' );
69 }
70
71 /**
72 * Load persistent module-data from the WP Database.
73 *
74 * @since 1.0.0
75 */
76 protected function read_stored_data() {
77 $data = get_site_option( 'wdev-frash', false, false );
78
79 if ( ! is_array( $data ) ) {
80 $data = array();
81 }
82
83 // A list of all plugins with timestamp of first registration.
84 if ( ! isset( $data['plugins'] ) || ! is_array( $data['plugins'] ) ) {
85 $data['plugins'] = array();
86 }
87
88 // A list with pending messages and earliest timestamp for display.
89 if ( ! isset( $data['queue'] ) || ! is_array( $data['queue'] ) ) {
90 $data['queue'] = array();
91 }
92
93 // A list with all messages that were handles already.
94 if ( ! isset( $data['done'] ) || ! is_array( $data['done'] ) ) {
95 $data['done'] = array();
96 }
97
98 $this->stored = $data;
99 }
100
101 /**
102 * Save persistent module-data to the WP database.
103 *
104 * @since 1.0.0
105 */
106 protected function store_data() {
107 update_site_option( 'wdev-frash', $this->stored );
108 }
109
110 /**
111 * Action handler for 'wdev-register-plugin'
112 * Register an active plugin.
113 *
114 * @since 1.0.0
115 * @param string $plugin_id WordPress plugin-ID (see: plugin_basename).
116 * @param string $title Plugin name for display.
117 * @param string $url_wp URL to the plugin on wp.org (domain not needed)
118 * @param string $cta_email Title of the Email CTA button.
119 * @param string $mc_list_id required. Mailchimp mailing list id for the plugin.
120 */
121 public function wdev_register_plugin( $plugin_id, $title, $url_wp, $cta_email = '', $mc_list_id = '' ) {
122 // Ignore incorrectly registered plugins to avoid errors later.
123 if ( empty( $plugin_id ) ) { return; }
124 if ( empty( $title ) ) { return; }
125 if ( empty( $url_wp ) ) { return; }
126
127 if ( false === strpos( $url_wp, '://' ) ) {
128 $url_wp = 'https://wordpress.org/' . trim( $url_wp, '/' );
129 }
130
131 $this->plugins[$plugin_id] = (object) array(
132 'id' => $plugin_id,
133 'title' => $title,
134 'url_wp' => $url_wp,
135 'cta_email' => $cta_email,
136 'mc_list_id' => $mc_list_id,
137 );
138
139 /*
140 * When the plugin is registered the first time we store some infos
141 * in the persistent module-data that help us later to find out
142 * if/which message should be displayed.
143 */
144 if ( empty( $this->stored['plugins'][$plugin_id] ) ) {
145 // First register the plugin permanently.
146 $this->stored['plugins'][$plugin_id] = time();
147
148 // Second schedule the messages to display.
149 $hash = md5( $plugin_id . '-email' );
150 $this->stored['queue'][$hash] = array(
151 'plugin' => $plugin_id,
152 'type' => 'email',
153 'show_at' => time(), // Earliest time to display note.
154 );
155
156 $hash = md5( $plugin_id . '-rate' );
157 $this->stored['queue'][$hash] = array(
158 'plugin' => $plugin_id,
159 'type' => 'rate',
160 'show_at' => time() + 7 * DAY_IN_SECONDS,
161 );
162
163 // Finally save the details.
164 $this->store_data();
165 }
166 }
167
168 /**
169 * Ajax handler called when the user chooses the CTA button.
170 *
171 * @since 1.0.0
172 */
173 public function wp_ajax_frash_act() {
174 $plugin = $_POST['plugin_id'];
175 $type = $_POST['type'];
176
177 $this->mark_as_done( $plugin, $type, 'ok' );
178
179 echo 1;
180 exit;
181 }
182
183 /**
184 * Ajax handler called when the user chooses the dismiss button.
185 *
186 * @since 1.0.0
187 */
188 public function wp_ajax_frash_dismiss() {
189 $plugin = $_POST['plugin_id'];
190 $type = $_POST['type'];
191
192 $this->mark_as_done( $plugin, $type, 'ignore' );
193
194 echo 1;
195 exit;
196 }
197
198 /**
199 * Action handler for 'load-index.php'
200 * Set-up the Dashboard notification.
201 *
202 * @since 1.0.0
203 */
204 public function load_index_php() {
205 if ( is_super_admin() ) {
206 $this->add_action( 'all_admin_notices' );
207 }
208 }
209
210 /**
211 * Action handler for 'admin_notices'
212 * Display the Dashboard notification.
213 *
214 * @since 1.0.0
215 */
216 public function all_admin_notices() {
217 $info = $this->choose_message();
218 if ( ! $info ) { return; }
219
220 $this->render_message( $info );
221 }
222
223 /**
224 * Check to see if there is a pending message to display and returns
225 * the message details if there is.
226 *
227 * Note that this function is only called on the main Dashboard screen
228 * and only when logged in as super-admin.
229 *
230 * @since 1.0.0
231 * @return object|false
232 * string $type [rate|email] Which message type?
233 * string $plugin WordPress plugin ID?
234 */
235 protected function choose_message() {
236 $obj = false;
237 $chosen = false;
238 $earliest = false;
239
240 $now = time();
241
242 // The "current" time can be changed via $_GET to test the module.
243 if ( defined( 'WP_DEBUG' ) && WP_DEBUG && ! empty( $_GET['time'] ) ) {
244 $custom_time = $_GET['time'];
245 if ( ' ' == $custom_time[0] ) { $custom_time[0] = '+'; }
246 if ( $custom_time ) { $now = strtotime( $custom_time ); }
247 if ( ! $now ) { $now = time(); }
248 }
249
250 $tomorrow = $now + DAY_IN_SECONDS;
251
252 foreach ( $this->stored['queue'] as $hash => $item ) {
253 $show_at = intval( $item['show_at'] );
254 $is_sticky = ! empty( $item['sticky'] );
255
256 if ( ! isset( $this->plugins[ $item['plugin'] ] ) ) {
257 // Deactivated plugin before the message was displayed.
258 continue;
259 }
260 $plugin = $this->plugins[ $item['plugin'] ];
261
262 $can_display = true;
263 if ( wp_is_mobile() ) {
264 // Do not display rating message on mobile devices.
265 if ( 'rate' == $item['type'] ) {
266 $can_display = false;
267 }
268 }
269 if ( 'email' == $item['type'] ) {
270 //If we don't have mailchimp list id
271 if ( ! $plugin->mc_list_id || ! $plugin->cta_email ) {
272 // Do not display email message with missing email params.
273 $can_display = false;
274 }
275 }
276 if ( $now < $show_at ) {
277 // Do not display messages that are not due yet.
278 $can_display = false;
279 }
280
281 if ( ! $can_display ) { continue; }
282
283 if ( $is_sticky ) {
284 // If sticky item is present then choose it!
285 $chosen = $hash;
286 break;
287 } elseif ( ! $earliest || $earliest < $show_at ) {
288 $earliest = $show_at;
289 $chosen = $hash;
290 // Don't use `break` because a sticky item might follow...
291 // Find the item with the earliest schedule.
292 }
293 }
294
295 if ( $chosen ) {
296 // Make the chosen item sticky.
297 $this->stored['queue'][$chosen]['sticky'] = true;
298
299 // Re-schedule other messages that are due today.
300 foreach ( $this->stored['queue'] as $hash => $item ) {
301 $show_at = intval( $item['show_at'] );
302
303 if ( empty( $item['sticky'] ) && $tomorrow > $show_at ) {
304 $this->stored['queue'][$hash]['show_at'] = $tomorrow;
305 }
306 }
307
308 // Save the changes.
309 $this->store_data();
310
311 $obj = (object) $this->stored['queue'][$chosen];
312 }
313
314 return $obj;
315 }
316
317 /**
318 * Moves a message from the queue to the done list.
319 *
320 * @since 1.0.0
321 * @param string $plugin Plugin ID.
322 * @param string $type [rate|email] Message type.
323 * @param string $state [ok|ignore] Button clicked.
324 */
325 protected function mark_as_done( $plugin, $type, $state ) {
326 $done_item = false;
327
328 foreach ( $this->stored['queue'] as $hash => $item ) {
329 unset( $this->stored['queue'][$hash]['sticky'] );
330
331 if ( $item['plugin'] == $plugin && $item['type'] == $type ) {
332 $done_item = $item;
333 unset( $this->stored['queue'][$hash] );
334 }
335 }
336
337 if ( $done_item ) {
338 $done_item['state'] = $state;
339 $done_item['hash'] = $hash;
340 $done_item['handled_at'] = time();
341 unset( $done_item['sticky'] );
342
343 $this->stored['done'][] = $done_item;
344 $this->store_data();
345 }
346 }
347
348 /**
349 * Renders the actual Notification message.
350 *
351 * @since 1.0.0
352 */
353 protected function render_message( $info ) {
354 $plugin = $this->plugins[$info->plugin];
355 $css_url = plugin_dir_url( __FILE__ ) . '/admin.css';
356 $js_url = plugin_dir_url( __FILE__ ) . '/admin.js';
357
358 ?>
359 <link rel="stylesheet" type="text/css" href="<?php echo esc_url( $css_url ); ?>" />
360 <div class="notice frash-notice frash-notice-<?php echo esc_attr( $info->type ); ?>" style="display:none">
361 <input type="hidden" name="type" value="<?php echo esc_attr( $info->type ); ?>" />
362 <input type="hidden" name="plugin_id" value="<?php echo esc_attr( $info->plugin ); ?>" />
363 <input type="hidden" name="url_wp" value="<?php echo esc_attr( $plugin->url_wp ); ?>" />
364 <?php
365 if ( 'email' == $info->type ) {
366 $this->render_email_message( $plugin );
367 } elseif ( 'rate' == $info->type ) {
368 $this->render_rate_message( $plugin );
369 }
370 ?>
371 </div>
372 <script src="<?php echo esc_url( $js_url ); ?>"></script>
373 <?php
374 }
375
376 /**
377 * Output the contents of the email message.
378 * No return value. The code is directly output.
379 *
380 * @since 1.0.0
381 */
382 protected function render_email_message( $plugin ) {
383 $admin_email = get_site_option( 'admin_email' );
384 $action = "https://edublogs.us1.list-manage.com/subscribe/post-json?u={$this->mc_user_id}&id={$plugin->mc_list_id}&c=?";
385
386 $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' );
387 $msg = apply_filters( 'wdev-email-message-' . $plugin->id, $msg );
388
389 ?>
390 <div class="frash-notice-logo"><span></span></div>
391 <div class="frash-notice-message">
392 <?php
393 printf(
394 $msg,
395 '<strong>' . $plugin->title . '</strong>'
396 );
397 ?>
398 </div>
399 <div class="frash-notice-cta">
400 <form action="<?php echo $action; ?>" method="get" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank">
401 <input type="email" name="EMAIL" class="email" id="mce-EMAIL" value="<?php echo esc_attr( $admin_email ); ?>" required="required"/>
402 <button class="frash-notice-act button-primary" data-msg="<?php _e( 'Thanks :)', 'wdev_frash' ); ?>" type="submit">
403 <?php echo esc_html( $plugin->cta_email ); ?>
404 </button>
405 <button class="frash-notice-dismiss" data-msg="<?php _e( 'Saving', 'wdev_frash' ); ?>">
406 <?php _e( 'No thanks', 'wdev_frash' ); ?>
407 </button>
408 </form>
409 </div>
410 <?php
411 }
412
413 /**
414 * Output the contents of the rate-this-plugin message.
415 * No return value. The code is directly output.
416 *
417 * @since 1.0.0
418 */
419 protected function render_rate_message( $plugin ) {
420 $user = wp_get_current_user();
421 $user_name = $user->display_name;
422
423 $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' );
424 $msg = apply_filters( 'wdev-rating-message-' . $plugin->id, $msg );
425
426 ?>
427 <div class="frash-notice-logo"><span></span></div>
428 <div class="frash-notice-message">
429 <?php
430 printf(
431 $msg,
432 '<strong>' . $user_name . '</strong>',
433 '<strong>' . $plugin->title . '</strong>'
434 );
435 ?>
436 </div>
437 <div class="frash-notice-cta">
438 <button class="frash-notice-act button-primary" data-msg="<?php _e( 'Thanks :)', 'wdev_frash' ); ?>">
439 <?php
440 printf(
441 __( 'Rate %s', 'wdev_frash' ),
442 esc_html( $plugin->title )
443 ); ?>
444 </button>
445 <button class="frash-notice-dismiss" data-msg="<?php _e( 'Saving', 'wdev_frash' ); ?>">
446 <?php _e( 'No thanks', 'wdev_frash' ); ?>
447 </button>
448 </div>
449 <?php
450 }
451
452 /**
453 * Registers a new action handler. The callback function has the same
454 * name as the action hook.
455 *
456 * @since 1.0.0
457 */
458 protected function add_action( $hook, $params = 1 ) {
459 $method_name = strtolower( $hook );
460 $method_name = preg_replace( '/[^a-z0-9]/', '_', $method_name );
461 $handler = array( $this, $method_name );
462 add_action( $hook, $handler, 5, $params );
463 }
464 }
465
466 // Initialize the module.
467 WDev_Frash::instance();
468 }