PageRenderTime 150ms CodeModel.GetById 41ms RepoModel.GetById 3ms app.codeStats 0ms

/wp-content/plugins/wp-smushit/extras/free-dashboard/module.php

https://gitlab.com/bhargavi_dcw/dflocal
PHP | 457 lines | 264 code | 58 blank | 135 comment | 46 complexity | aeb98c8e70a7c4c803d98868ec7eee33 MD5 | raw file
  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. * List of all registered plugins.
  13. *
  14. * @since 1.0.0
  15. * @var array
  16. */
  17. protected $plugins = array();
  18. /**
  19. * Module options that are stored in database.
  20. * Timestamps are stored here.
  21. *
  22. * Note that this option is stored in site-meta for multisite installs.
  23. *
  24. * @since 1.0.0
  25. * @var array
  26. */
  27. protected $stored = array();
  28. /**
  29. * Initializes and returns the singleton instance.
  30. *
  31. * @since 1.0.0
  32. */
  33. static public function instance() {
  34. static $Inst = null;
  35. if ( null === $Inst ) {
  36. $Inst = new WDev_Frash();
  37. }
  38. return $Inst;
  39. }
  40. /**
  41. * Set up the WDev_Frash module. Private singleton constructor.
  42. *
  43. * @since 1.0.0
  44. */
  45. private function __construct() {
  46. $this->read_stored_data();
  47. $this->add_action( 'wdev-register-plugin', 5 );
  48. $this->add_action( 'load-index.php' );
  49. $this->add_action( 'wp_ajax_frash_act' );
  50. $this->add_action( 'wp_ajax_frash_dismiss' );
  51. }
  52. /**
  53. * Load persistent module-data from the WP Database.
  54. *
  55. * @since 1.0.0
  56. */
  57. protected function read_stored_data() {
  58. $data = get_site_option( 'wdev-frash', false, false );
  59. if ( ! is_array( $data ) ) {
  60. $data = array();
  61. }
  62. // A list of all plugins with timestamp of first registration.
  63. if ( ! isset( $data['plugins'] ) || ! is_array( $data['plugins'] ) ) {
  64. $data['plugins'] = array();
  65. }
  66. // A list with pending messages and earliest timestamp for display.
  67. if ( ! isset( $data['queue'] ) || ! is_array( $data['queue'] ) ) {
  68. $data['queue'] = array();
  69. }
  70. // A list with all messages that were handles already.
  71. if ( ! isset( $data['done'] ) || ! is_array( $data['done'] ) ) {
  72. $data['done'] = array();
  73. }
  74. $this->stored = $data;
  75. }
  76. /**
  77. * Save persistent module-data to the WP database.
  78. *
  79. * @since 1.0.0
  80. */
  81. protected function store_data() {
  82. update_site_option( 'wdev-frash', $this->stored );
  83. }
  84. /**
  85. * Action handler for 'wdev-register-plugin'
  86. * Register an active plugin.
  87. *
  88. * @since 1.0.0
  89. * @param string $plugin_id WordPress plugin-ID (see: plugin_basename).
  90. * @param string $title Plugin name for display.
  91. * @param string $url_wp URL to the plugin on wp.org (domain not needed)
  92. * @param string $cta_email Title of the Email CTA button.
  93. * @param string $drip_plugin Optional. Plugin-param for the getdrip rule.
  94. */
  95. public function wdev_register_plugin( $plugin_id, $title, $url_wp, $cta_email = '', $drip_plugin = '' ) {
  96. // Ignore incorrectly registered plugins to avoid errors later.
  97. if ( empty( $plugin_id ) ) { return; }
  98. if ( empty( $title ) ) { return; }
  99. if ( empty( $url_wp ) ) { return; }
  100. if ( false === strpos( $url_wp, '://' ) ) {
  101. $url_wp = 'https://wordpress.org/' . trim( $url_wp, '/' );
  102. }
  103. $this->plugins[$plugin_id] = (object) array(
  104. 'id' => $plugin_id,
  105. 'title' => $title,
  106. 'url_wp' => $url_wp,
  107. 'cta_email' => $cta_email,
  108. 'drip_plugin' => $drip_plugin,
  109. );
  110. /*
  111. * When the plugin is registered the first time we store some infos
  112. * in the persistent module-data that help us later to find out
  113. * if/which message should be displayed.
  114. */
  115. if ( empty( $this->stored['plugins'][$plugin_id] ) ) {
  116. // First register the plugin permanently.
  117. $this->stored['plugins'][$plugin_id] = time();
  118. // Second schedule the messages to display.
  119. $hash = md5( $plugin_id . '-email' );
  120. $this->stored['queue'][$hash] = array(
  121. 'plugin' => $plugin_id,
  122. 'type' => 'email',
  123. 'show_at' => time(), // Earliest time to display note.
  124. );
  125. $hash = md5( $plugin_id . '-rate' );
  126. $this->stored['queue'][$hash] = array(
  127. 'plugin' => $plugin_id,
  128. 'type' => 'rate',
  129. 'show_at' => time() + 7 * DAY_IN_SECONDS,
  130. );
  131. // Finally save the details.
  132. $this->store_data();
  133. }
  134. }
  135. /**
  136. * Ajax handler called when the user chooses the CTA button.
  137. *
  138. * @since 1.0.0
  139. */
  140. public function wp_ajax_frash_act() {
  141. $plugin = $_POST['plugin_id'];
  142. $type = $_POST['type'];
  143. $this->mark_as_done( $plugin, $type, 'ok' );
  144. echo 1;
  145. exit;
  146. }
  147. /**
  148. * Ajax handler called when the user chooses the dismiss button.
  149. *
  150. * @since 1.0.0
  151. */
  152. public function wp_ajax_frash_dismiss() {
  153. $plugin = $_POST['plugin_id'];
  154. $type = $_POST['type'];
  155. $this->mark_as_done( $plugin, $type, 'ignore' );
  156. echo 1;
  157. exit;
  158. }
  159. /**
  160. * Action handler for 'load-index.php'
  161. * Set-up the Dashboard notification.
  162. *
  163. * @since 1.0.0
  164. */
  165. public function load_index_php() {
  166. if ( is_super_admin() ) {
  167. $this->add_action( 'all_admin_notices' );
  168. }
  169. }
  170. /**
  171. * Action handler for 'admin_notices'
  172. * Display the Dashboard notification.
  173. *
  174. * @since 1.0.0
  175. */
  176. public function all_admin_notices() {
  177. $info = $this->choose_message();
  178. if ( ! $info ) { return; }
  179. $this->render_message( $info );
  180. }
  181. /**
  182. * Check to see if there is a pending message to display and returns
  183. * the message details if there is.
  184. *
  185. * Note that this function is only called on the main Dashboard screen
  186. * and only when logged in as super-admin.
  187. *
  188. * @since 1.0.0
  189. * @return object|false
  190. * string $type [rate|email] Which message type?
  191. * string $plugin WordPress plugin ID?
  192. */
  193. protected function choose_message() {
  194. $obj = false;
  195. $chosen = false;
  196. $earliest = false;
  197. $now = time();
  198. // The "current" time can be changed via $_GET to test the module.
  199. if ( defined( 'WP_DEBUG' ) && WP_DEBUG && ! empty( $_GET['time'] ) ) {
  200. $custom_time = $_GET['time'];
  201. if ( ' ' == $custom_time[0] ) { $custom_time[0] = '+'; }
  202. if ( $custom_time ) { $now = strtotime( $custom_time ); }
  203. if ( ! $now ) { $now = time(); }
  204. }
  205. $tomorrow = $now + DAY_IN_SECONDS;
  206. foreach ( $this->stored['queue'] as $hash => $item ) {
  207. $show_at = intval( $item['show_at'] );
  208. $is_sticky = ! empty( $item['sticky'] );
  209. if ( ! isset( $this->plugins[ $item['plugin'] ] ) ) {
  210. // Deactivated plugin before the message was displayed.
  211. continue;
  212. }
  213. $plugin = $this->plugins[ $item['plugin'] ];
  214. $can_display = true;
  215. if ( wp_is_mobile() ) {
  216. // Do not display rating message on mobile devices.
  217. if ( 'rate' == $item['type'] ) {
  218. $can_display = false;
  219. }
  220. }
  221. if ( 'email' == $item['type'] ) {
  222. if ( ! $plugin->drip_plugin || ! $plugin->cta_email ) {
  223. // Do not display email message with missing email params.
  224. $can_display = false;
  225. }
  226. }
  227. if ( $now < $show_at ) {
  228. // Do not display messages that are not due yet.
  229. $can_display = false;
  230. }
  231. if ( ! $can_display ) { continue; }
  232. if ( $is_sticky ) {
  233. // If sticky item is present then choose it!
  234. $chosen = $hash;
  235. break;
  236. } elseif ( ! $earliest || $earliest < $show_at ) {
  237. $earliest = $show_at;
  238. $chosen = $hash;
  239. // Don't use `break` because a sticky item might follow...
  240. // Find the item with the earliest schedule.
  241. }
  242. }
  243. if ( $chosen ) {
  244. // Make the chosen item sticky.
  245. $this->stored['queue'][$chosen]['sticky'] = true;
  246. // Re-schedule other messages that are due today.
  247. foreach ( $this->stored['queue'] as $hash => $item ) {
  248. $show_at = intval( $item['show_at'] );
  249. if ( empty( $item['sticky'] ) && $tomorrow > $show_at ) {
  250. $this->stored['queue'][$hash]['show_at'] = $tomorrow;
  251. }
  252. }
  253. // Save the changes.
  254. $this->store_data();
  255. $obj = (object) $this->stored['queue'][$chosen];
  256. }
  257. return $obj;
  258. }
  259. /**
  260. * Moves a message from the queue to the done list.
  261. *
  262. * @since 1.0.0
  263. * @param string $plugin Plugin ID.
  264. * @param string $type [rate|email] Message type.
  265. * @param string $state [ok|ignore] Button clicked.
  266. */
  267. protected function mark_as_done( $plugin, $type, $state ) {
  268. $done_item = false;
  269. foreach ( $this->stored['queue'] as $hash => $item ) {
  270. unset( $this->stored['queue'][$hash]['sticky'] );
  271. if ( $item['plugin'] == $plugin && $item['type'] == $type ) {
  272. $done_item = $item;
  273. unset( $this->stored['queue'][$hash] );
  274. }
  275. }
  276. if ( $done_item ) {
  277. $done_item['state'] = $state;
  278. $done_item['hash'] = $hash;
  279. $done_item['handled_at'] = time();
  280. unset( $done_item['sticky'] );
  281. $this->stored['done'][] = $done_item;
  282. $this->store_data();
  283. }
  284. }
  285. /**
  286. * Renders the actual Notification message.
  287. *
  288. * @since 1.0.0
  289. */
  290. protected function render_message( $info ) {
  291. $plugin = $this->plugins[$info->plugin];
  292. $css_url = plugin_dir_url( __FILE__ ) . '/admin.css';
  293. $js_url = plugin_dir_url( __FILE__ ) . '/admin.js';
  294. ?>
  295. <link rel="stylesheet" type="text/css" href="<?php echo esc_url( $css_url ); ?>" />
  296. <div class="notice frash-notice frash-notice-<?php echo esc_attr( $info->type ); ?>" style="display:none">
  297. <input type="hidden" name="type" value="<?php echo esc_attr( $info->type ); ?>" />
  298. <input type="hidden" name="plugin_id" value="<?php echo esc_attr( $info->plugin ); ?>" />
  299. <input type="hidden" name="url_wp" value="<?php echo esc_attr( $plugin->url_wp ); ?>" />
  300. <input type="hidden" name="drip_plugin" value="<?php echo esc_attr( $plugin->drip_plugin ); ?>" />
  301. <?php
  302. if ( 'email' == $info->type ) {
  303. $this->render_email_message( $plugin );
  304. } elseif ( 'rate' == $info->type ) {
  305. $this->render_rate_message( $plugin );
  306. }
  307. ?>
  308. </div>
  309. <script src="<?php echo esc_url( $js_url ); ?>"></script>
  310. <?php
  311. }
  312. /**
  313. * Output the contents of the email message.
  314. * No return value. The code is directly output.
  315. *
  316. * @since 1.0.0
  317. */
  318. protected function render_email_message( $plugin ) {
  319. $user = wp_get_current_user();
  320. $user_name = $user->display_name;
  321. $admin_email = get_site_option( 'admin_email' );
  322. $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' );
  323. $msg = apply_filters( 'wdev-email-message-' . $plugin->id, $msg );
  324. ?>
  325. <div class="frash-notice-logo"><span></span></div>
  326. <div class="frash-notice-message">
  327. <?php
  328. printf(
  329. $msg,
  330. '<strong>' . $plugin->title . '</strong>'
  331. );
  332. ?>
  333. </div>
  334. <div class="frash-notice-cta">
  335. <input type="email" name="email" value="<?php echo esc_attr( $admin_email ); ?>" />
  336. <button class="frash-notice-act button-primary" data-msg="<?php _e( 'Thanks :)', 'wdev_frash' ); ?>">
  337. <?php echo esc_html( $plugin->cta_email ); ?>
  338. </button>
  339. <button class="frash-notice-dismiss" data-msg="<?php _e( 'Saving', 'wdev_frash' ); ?>">
  340. <?php _e( 'No thanks', 'wdev_frash' ); ?>
  341. </button>
  342. </div>
  343. <?php
  344. }
  345. /**
  346. * Output the contents of the rate-this-plugin message.
  347. * No return value. The code is directly output.
  348. *
  349. * @since 1.0.0
  350. */
  351. protected function render_rate_message( $plugin ) {
  352. $user = wp_get_current_user();
  353. $user_name = $user->display_name;
  354. $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' );
  355. $msg = apply_filters( 'wdev-rating-message-' . $plugin->id, $msg );
  356. ?>
  357. <div class="frash-notice-logo"><span></span></div>
  358. <div class="frash-notice-message">
  359. <?php
  360. printf(
  361. $msg,
  362. '<strong>' . $user_name . '</strong>',
  363. '<strong>' . $plugin->title . '</strong>'
  364. );
  365. ?>
  366. </div>
  367. <div class="frash-notice-cta">
  368. <button class="frash-notice-act button-primary" data-msg="<?php _e( 'Thanks :)', 'wdev_frash' ); ?>">
  369. <?php
  370. printf(
  371. __( 'Rate %s', 'wdev_frash' ),
  372. esc_html( $plugin->title )
  373. ); ?>
  374. </button>
  375. <button class="frash-notice-dismiss" data-msg="<?php _e( 'Saving', 'wdev_frash' ); ?>">
  376. <?php _e( 'No thanks', 'wdev_frash' ); ?>
  377. </button>
  378. </div>
  379. <?php
  380. }
  381. /**
  382. * Registers a new action handler. The callback function has the same
  383. * name as the action hook.
  384. *
  385. * @since 1.0.0
  386. */
  387. protected function add_action( $hook, $params = 1 ) {
  388. $method_name = strtolower( $hook );
  389. $method_name = preg_replace( '/[^a-z0-9]/', '_', $method_name );
  390. $handler = array( $this, $method_name );
  391. add_action( $hook, $handler, 5, $params );
  392. }
  393. }
  394. // Initialize the module.
  395. WDev_Frash::instance();
  396. }