read_stored_data(); $this->add_action( 'wdev-register-plugin', 5 ); $this->add_action( 'load-index.php' ); $this->add_action( 'wp_ajax_frash_act' ); $this->add_action( 'wp_ajax_frash_dismiss' ); } /** * Load persistent module-data from the WP Database. * * @since 1.0.0 */ protected function read_stored_data() { $data = get_site_option( 'wdev-frash', false, false ); if ( ! is_array( $data ) ) { $data = array(); } // A list of all plugins with timestamp of first registration. if ( ! isset( $data['plugins'] ) || ! is_array( $data['plugins'] ) ) { $data['plugins'] = array(); } // A list with pending messages and earliest timestamp for display. if ( ! isset( $data['queue'] ) || ! is_array( $data['queue'] ) ) { $data['queue'] = array(); } // A list with all messages that were handles already. if ( ! isset( $data['done'] ) || ! is_array( $data['done'] ) ) { $data['done'] = array(); } $this->stored = $data; } /** * Save persistent module-data to the WP database. * * @since 1.0.0 */ protected function store_data() { update_site_option( 'wdev-frash', $this->stored ); } /** * Action handler for 'wdev-register-plugin' * Register an active plugin. * * @since 1.0.0 * @param string $plugin_id WordPress plugin-ID (see: plugin_basename). * @param string $title Plugin name for display. * @param string $url_wp URL to the plugin on wp.org (domain not needed) * @param string $cta_email Title of the Email CTA button. * @param string $drip_plugin Optional. Plugin-param for the getdrip rule. */ public function wdev_register_plugin( $plugin_id, $title, $url_wp, $cta_email = '', $drip_plugin = '' ) { // Ignore incorrectly registered plugins to avoid errors later. if ( empty( $plugin_id ) ) { return; } if ( empty( $title ) ) { return; } if ( empty( $url_wp ) ) { return; } if ( false === strpos( $url_wp, '://' ) ) { $url_wp = 'https://wordpress.org/' . trim( $url_wp, '/' ); } $this->plugins[$plugin_id] = (object) array( 'id' => $plugin_id, 'title' => $title, 'url_wp' => $url_wp, 'cta_email' => $cta_email, 'drip_plugin' => $drip_plugin, ); /* * When the plugin is registered the first time we store some infos * in the persistent module-data that help us later to find out * if/which message should be displayed. */ if ( empty( $this->stored['plugins'][$plugin_id] ) ) { // First register the plugin permanently. $this->stored['plugins'][$plugin_id] = time(); // Second schedule the messages to display. $hash = md5( $plugin_id . '-email' ); $this->stored['queue'][$hash] = array( 'plugin' => $plugin_id, 'type' => 'email', 'show_at' => time(), // Earliest time to display note. ); $hash = md5( $plugin_id . '-rate' ); $this->stored['queue'][$hash] = array( 'plugin' => $plugin_id, 'type' => 'rate', 'show_at' => time() + 7 * DAY_IN_SECONDS, ); // Finally save the details. $this->store_data(); } } /** * Ajax handler called when the user chooses the CTA button. * * @since 1.0.0 */ public function wp_ajax_frash_act() { $plugin = $_POST['plugin_id']; $type = $_POST['type']; $this->mark_as_done( $plugin, $type, 'ok' ); echo 1; exit; } /** * Ajax handler called when the user chooses the dismiss button. * * @since 1.0.0 */ public function wp_ajax_frash_dismiss() { $plugin = $_POST['plugin_id']; $type = $_POST['type']; $this->mark_as_done( $plugin, $type, 'ignore' ); echo 1; exit; } /** * Action handler for 'load-index.php' * Set-up the Dashboard notification. * * @since 1.0.0 */ public function load_index_php() { if ( is_super_admin() ) { $this->add_action( 'all_admin_notices' ); } } /** * Action handler for 'admin_notices' * Display the Dashboard notification. * * @since 1.0.0 */ public function all_admin_notices() { $info = $this->choose_message(); if ( ! $info ) { return; } $this->render_message( $info ); } /** * Check to see if there is a pending message to display and returns * the message details if there is. * * Note that this function is only called on the main Dashboard screen * and only when logged in as super-admin. * * @since 1.0.0 * @return object|false * string $type [rate|email] Which message type? * string $plugin WordPress plugin ID? */ protected function choose_message() { $obj = false; $chosen = false; $earliest = false; $now = time(); // The "current" time can be changed via $_GET to test the module. if ( defined( 'WP_DEBUG' ) && WP_DEBUG && ! empty( $_GET['time'] ) ) { $custom_time = $_GET['time']; if ( ' ' == $custom_time[0] ) { $custom_time[0] = '+'; } if ( $custom_time ) { $now = strtotime( $custom_time ); } if ( ! $now ) { $now = time(); } } $tomorrow = $now + DAY_IN_SECONDS; foreach ( $this->stored['queue'] as $hash => $item ) { $show_at = intval( $item['show_at'] ); $is_sticky = ! empty( $item['sticky'] ); if ( ! isset( $this->plugins[ $item['plugin'] ] ) ) { // Deactivated plugin before the message was displayed. continue; } $plugin = $this->plugins[ $item['plugin'] ]; $can_display = true; if ( wp_is_mobile() ) { // Do not display rating message on mobile devices. if ( 'rate' == $item['type'] ) { $can_display = false; } } if ( 'email' == $item['type'] ) { if ( ! $plugin->drip_plugin || ! $plugin->cta_email ) { // Do not display email message with missing email params. $can_display = false; } } if ( $now < $show_at ) { // Do not display messages that are not due yet. $can_display = false; } if ( ! $can_display ) { continue; } if ( $is_sticky ) { // If sticky item is present then choose it! $chosen = $hash; break; } elseif ( ! $earliest || $earliest < $show_at ) { $earliest = $show_at; $chosen = $hash; // Don't use `break` because a sticky item might follow... // Find the item with the earliest schedule. } } if ( $chosen ) { // Make the chosen item sticky. $this->stored['queue'][$chosen]['sticky'] = true; // Re-schedule other messages that are due today. foreach ( $this->stored['queue'] as $hash => $item ) { $show_at = intval( $item['show_at'] ); if ( empty( $item['sticky'] ) && $tomorrow > $show_at ) { $this->stored['queue'][$hash]['show_at'] = $tomorrow; } } // Save the changes. $this->store_data(); $obj = (object) $this->stored['queue'][$chosen]; } return $obj; } /** * Moves a message from the queue to the done list. * * @since 1.0.0 * @param string $plugin Plugin ID. * @param string $type [rate|email] Message type. * @param string $state [ok|ignore] Button clicked. */ protected function mark_as_done( $plugin, $type, $state ) { $done_item = false; foreach ( $this->stored['queue'] as $hash => $item ) { unset( $this->stored['queue'][$hash]['sticky'] ); if ( $item['plugin'] == $plugin && $item['type'] == $type ) { $done_item = $item; unset( $this->stored['queue'][$hash] ); } } if ( $done_item ) { $done_item['state'] = $state; $done_item['hash'] = $hash; $done_item['handled_at'] = time(); unset( $done_item['sticky'] ); $this->stored['done'][] = $done_item; $this->store_data(); } } /** * Renders the actual Notification message. * * @since 1.0.0 */ protected function render_message( $info ) { $plugin = $this->plugins[$info->plugin]; $css_url = plugin_dir_url( __FILE__ ) . '/admin.css'; $js_url = plugin_dir_url( __FILE__ ) . '/admin.js'; ?> display_name; $admin_email = get_site_option( 'admin_email' ); $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!", self::LANG ); $msg = apply_filters( 'wdev-email-message-' . $plugin->id, $msg ); ?>
' . $plugin->title . '' ); ?>
display_name; $msg = __( "Hey %s, you've been using %s for a while now, and we hope you're happy with it.", self::LANG ) . '
'. __( "We've spent countless hours developing this free plugin for you, and we would really appreciate it if you dropped us a quick rating!", self::LANG ); $msg = apply_filters( 'wdev-rating-message-' . $plugin->id, $msg ); ?>
' . $user_name . '', '' . $plugin->title . '' ); ?>