Нет описания

Onboarding.php 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. <?php
  2. if ( ! defined( 'ABSPATH' ) ) {
  3. exit;
  4. }
  5. /**
  6. * Handles all onboarding throughout site admin areas.
  7. *
  8. * @since 1.11.0
  9. */
  10. class PUM_Admin_Onboarding {
  11. /**
  12. * Enqueues and sets up pointers across our admin pages.
  13. */
  14. public static function init() {
  15. if ( is_admin() && current_user_can( 'manage_options' ) ) {
  16. add_filter( 'pum_alert_list', array( __CLASS__, 'tips_alert' ) );
  17. add_action( 'pum_alert_dismissed', array( __CLASS__, 'alert_handler' ), 10, 2 );
  18. }
  19. add_filter( 'pum_admin_pointers-popup', array( __CLASS__, 'popup_editor_main_tour' ) );
  20. add_filter( 'pum_admin_pointers-edit-popup', array( __CLASS__, 'all_popups_main_tour' ) );
  21. add_action( 'admin_enqueue_scripts', array( __CLASS__, 'set_up_pointers' ) );
  22. add_action( 'admin_init', array( __CLASS__, 'welcome_redirect' ) );
  23. if ( ! empty( $_GET['page'] ) && 'pum-welcome' === $_GET['page'] ) {
  24. add_action( 'admin_menu', array( __CLASS__, 'set_up_welcome_page' ) );
  25. }
  26. }
  27. /**
  28. * Adds a 'tip' alert occasionally inside PM's admin area
  29. *
  30. * @param array $alerts The alerts currently in the alert system.
  31. * @return array Alerts for the alert system.
  32. * @since 1.13.0
  33. */
  34. public static function tips_alert( $alerts ) {
  35. if ( ! self::should_show_tip() ) {
  36. return $alerts;
  37. }
  38. $tip = self::get_random_tip();
  39. $alerts[] = array(
  40. 'code' => 'pum_tip_alert',
  41. 'type' => 'info',
  42. 'message' => $tip['msg'],
  43. 'priority' => 10,
  44. 'dismissible' => '1 month',
  45. 'global' => false,
  46. 'actions' => array(
  47. array(
  48. 'primary' => true,
  49. 'type' => 'link',
  50. 'action' => '',
  51. 'href' => $tip['link'],
  52. 'text' => __( 'Learn more', 'popup-maker' ),
  53. ),
  54. array(
  55. 'primary' => false,
  56. 'type' => 'action',
  57. 'action' => 'dismiss',
  58. 'text' => __( 'Dismiss', 'popup-maker' ),
  59. ),
  60. array(
  61. 'primary' => false,
  62. 'type' => 'action',
  63. 'action' => 'disable_tips',
  64. 'text' => __( 'Turn off these occasional tips', 'popup-maker' ),
  65. ),
  66. ),
  67. );
  68. return $alerts;
  69. }
  70. /**
  71. * Checks if any options have been clicked from admin notices.
  72. *
  73. * @param string $code The code for the alert.
  74. * @param string $action Action taken on the alert.
  75. * @since 1.13.0
  76. */
  77. public static function alert_handler( $code, $action ) {
  78. if ( 'pum_tip_alert' === $code ) {
  79. if ( 'disable_tips' === $action ) {
  80. pum_update_option( 'disable_tips', true );
  81. }
  82. }
  83. }
  84. /**
  85. * Sets up all guided tours for Popup Maker
  86. *
  87. * @since 1.11.0
  88. */
  89. public static function set_up_pointers() {
  90. if ( ! current_user_can( 'manage_options' ) ) {
  91. return;
  92. }
  93. $pointers = self::get_pointers_by_screen();
  94. // Get dismissed pointers.
  95. $dismissed = self::get_dismissed_pointers();
  96. $valid_pointers = array();
  97. // Cycles through pointers and only add valid ones.
  98. foreach ( $pointers as $pointer_id => $pointer ) {
  99. // Skip if pointer isn't an array.
  100. if ( ! is_array( $pointer ) ) {
  101. continue;
  102. }
  103. $pointer['pointer_id'] = $pointer_id;
  104. // Skip if pointer is not valid.
  105. if ( ! self::is_pointer_valid( $pointer ) ) {
  106. continue;
  107. }
  108. // Skip if pointer has already been dismissed.
  109. if ( in_array( $pointer_id, $dismissed ) )
  110. continue;
  111. // Add the pointer to $valid_pointers array.
  112. $valid_pointers['pointers'][] = $pointer;
  113. }
  114. // Bail out if there are no pointers to display.
  115. if ( empty( $valid_pointers ) ) {
  116. return;
  117. }
  118. // Add pointers style to queue.
  119. wp_enqueue_style( 'wp-pointer' );
  120. // Add pointers script to queue. Add custom script.
  121. wp_enqueue_script( 'pum-pointer', Popup_Maker::$URL . 'assets/js/admin-pointer.js', array( 'wp-pointer' ), Popup_Maker::$VER, true );
  122. // Add pointer options to script.
  123. wp_localize_script( 'pum-pointer', 'pumPointers', $valid_pointers );
  124. }
  125. /**
  126. * Retrieves the pointers for the given screen or current screen
  127. *
  128. * @param bool|WP_Screen $screen Pass false for current screen.
  129. * @return array
  130. * @since 1.11.0
  131. */
  132. public static function get_pointers_by_screen( $screen = false ) {
  133. if ( false === $screen || ! is_a( $screen, 'WP_Screen' ) ) {
  134. $screen = get_current_screen();
  135. }
  136. $screen_id = $screen->id;
  137. $pointers = apply_filters( 'pum_admin_pointers-' . $screen_id, array() );
  138. if ( ! $pointers || ! is_array( $pointers ) ) {
  139. return array();
  140. }
  141. return $pointers;
  142. }
  143. /**
  144. * Appends our main tour for the popup editor to pointers.
  145. *
  146. * @param array $pointers The pointers added to the screen.
  147. * @return array $pointers The updated pointers array.
  148. * @since 1.11.0
  149. */
  150. public static function popup_editor_main_tour( $pointers ) {
  151. /**
  152. * For the position, the 'edge' is used as the second parameter
  153. * in jQuery's "at" with the opposite in jQuery's "my".
  154. * The optional align is used as the first parameter in both "at" and "my".
  155. *
  156. * @see https://github.com/WordPress/WordPress/blob/master/wp-includes/js/wp-pointer.js#L295
  157. * @see https://jqueryui.com/position/
  158. */
  159. $pointers['popup-editor-1'] = array(
  160. 'target' => '#title',
  161. 'options' => array(
  162. 'content' => sprintf( '<h3> %s </h3> <p> %s </p>',
  163. __( 'Popup Name' ,'popup-maker'),
  164. __( 'Name your popup so you can find it later. Site visitors will not see this.','popup-maker')
  165. ),
  166. 'position' => array( 'edge' => 'top', 'align' => 'center' ),
  167. )
  168. );
  169. $pointers['popup-editor-2'] = array(
  170. 'target' => '#wp-content-editor-container',
  171. 'options' => array(
  172. 'content' => sprintf( '<h3> %s </h3> <p> %s </p>',
  173. __( 'Popup Content' ,'popup-maker'),
  174. __( 'Add content for your popup here.','popup-maker')
  175. ),
  176. 'position' => array( 'edge' => 'bottom', 'align' => 'center' ),
  177. )
  178. );
  179. $pointers['popup-editor-3'] = array(
  180. 'target' => 'a[href="#pum-popup-settings_triggers"]',
  181. 'options' => array(
  182. 'content' => sprintf( '<h3> %s </h3> <p> %s </p>',
  183. __( 'Popup Triggers' ,'popup-maker'),
  184. __( 'Use triggers to choose what causes the popup to open.','popup-maker')
  185. ),
  186. 'position' => array( 'edge' => 'left', 'align' => 'center' ),
  187. )
  188. );
  189. $pointers['popup-editor-4'] = array(
  190. 'target' => 'a[href="#pum-popup-settings_targeting"]',
  191. 'options' => array(
  192. 'content' => sprintf( '<h3> %s </h3> <p> %s </p>',
  193. __( 'Popup Targeting' ,'popup-maker'),
  194. __( 'Use targeting to choose where on your site the popup should load and who to show the popup to.','popup-maker')
  195. ),
  196. 'position' => array( 'edge' => 'left', 'align' => 'center' ),
  197. )
  198. );
  199. $pointers['popup-editor-5'] = array(
  200. 'target' => 'a[href="#pum-popup-settings_display"]',
  201. 'options' => array(
  202. 'content' => sprintf( '<h3> %s </h3> <p> %s </p>',
  203. __( 'Popup Display' ,'popup-maker'),
  204. __( 'Use display settings to choose where on the screen the popup appears and what it looks like.','popup-maker')
  205. ),
  206. 'position' => array( 'edge' => 'left', 'align' => 'center' ),
  207. )
  208. );
  209. $pointers['popup-editor-6'] = array(
  210. 'target' => 'select#theme_id',
  211. 'options' => array(
  212. 'content' => sprintf( '<h3> %s </h3> <p> %s </p>',
  213. __( 'Popup Theme' ,'popup-maker'),
  214. __( 'Choose the popup theme which controls the visual appearance of your popup including; colors, spacing, and fonts.','popup-maker')
  215. ),
  216. 'position' => array( 'edge' => 'bottom', 'align' => 'left' ),
  217. ),
  218. 'pre' => array(
  219. 'clicks' => array(
  220. 'a[href="#pum-popup-settings_display"]',
  221. 'a[href="#pum-popup-settings-display-subtabs_main"]',
  222. ),
  223. ),
  224. );
  225. return $pointers;
  226. }
  227. /**
  228. * Appends our main tour for the All Popups page.
  229. *
  230. * @param array $pointers The pointers added to the screen.
  231. * @return array $pointers The updated pointers array.
  232. * @since 1.11.0
  233. */
  234. public static function all_popups_main_tour( $pointers ) {
  235. $pointers['all-popups-1'] = array(
  236. 'target' => 'nav.nav-tab-wrapper a:nth-child(4)',
  237. 'options' => array(
  238. 'content' => sprintf(
  239. '<h3> %s </h3> <p> %s </p>',
  240. __( 'Welcome to Popup Maker!', 'popup-maker' ),
  241. __( 'Click the "Create New Popup" button to create your first popup.', 'popup-maker' )
  242. ),
  243. 'position' => array( 'edge' => 'top' ),
  244. ),
  245. );
  246. $pointers['all-popups-2'] = array(
  247. 'target' => '.wp-list-table #the-list tr:first-child .column-enabled',
  248. 'options' => array(
  249. 'content' => sprintf(
  250. '<h3> %s </h3> <p> %s </p>',
  251. __( 'Enable Popups', 'popup-maker' ),
  252. __( 'You can enable or disable your popups at any time using this toggle.', 'popup-maker' )
  253. ),
  254. 'position' => array(
  255. 'edge' => 'top',
  256. 'align' => 'left',
  257. ),
  258. ),
  259. );
  260. $pointers['all-popups-3'] = array(
  261. 'target' => '.wp-list-table #the-list tr:first-child .column-conversions',
  262. 'options' => array(
  263. 'content' => sprintf(
  264. '<h3> %s </h3> <p> %s </p>',
  265. __( 'Review Popup Metrics', 'popup-maker' ),
  266. __( 'Popup Maker will automatically track opens and conversions so you can easily see which popups convert the best.', 'popup-maker' )
  267. ),
  268. 'position' => array(
  269. 'edge' => 'top',
  270. 'align' => 'left',
  271. ),
  272. ),
  273. );
  274. $pointers['all-popups-4'] = array(
  275. 'target' => '#screen-options-link-wrap #show-settings-link',
  276. 'options' => array(
  277. 'content' => sprintf(
  278. '<h3> %s </h3> <p> %s </p>',
  279. __( 'Adjust Columns', 'popup-maker' ),
  280. __( 'You can show or hide columns from the table on this page using the Screen Options. Popup Heading and Published Date are hidden by default.', 'popup-maker' )
  281. ),
  282. 'position' => array(
  283. 'edge' => 'top',
  284. 'align' => 'center',
  285. ),
  286. ),
  287. );
  288. return $pointers;
  289. }
  290. /**
  291. * Retrieves a random tip
  292. *
  293. * @return array An array containing tip
  294. * @since 1.13.0
  295. */
  296. public static function get_random_tip() {
  297. $tips = array(
  298. array(
  299. 'msg' => 'Did you know: Popup Maker has a setting to let you try to bypass adblockers? Enabling it randomizes cache filenames and other endpoints to try to get around adblockers.',
  300. 'link' => admin_url( 'edit.php?post_type=popup&page=pum-settings&tab=pum-settings_misc' ),
  301. ),
  302. array(
  303. 'msg' => "Want to use the block editor to create your popups? Enable it over on Popup Maker's settings page.",
  304. 'link' => admin_url( 'edit.php?post_type=popup&page=pum-settings' ),
  305. ),
  306. array(
  307. 'msg' => 'Using the Popup Maker menu in your admin bar, you can open and close popups, check conditions, reseet cookies, and more!',
  308. 'link' => 'https://docs.wppopupmaker.com/article/300-the-popup-maker-admin-toolbar',
  309. ),
  310. array(
  311. 'msg' => "Did you know: You can easily customize your site's navigation to have a link open a popup by using the 'Trigger a Popup' option when editing your menus?",
  312. 'link' => 'https://docs.wppopupmaker.com/article/51-open-a-popup-from-a-wordpress-nav-menu',
  313. ),
  314. );
  315. if ( 7 < pum_count_popups() ) {
  316. $tips[] = array(
  317. 'msg' => 'Want to organize your popups? Enable categories on the settings page to group similar popups together!',
  318. 'link' => admin_url( 'edit.php?post_type=popup&page=pum-settings&tab=pum-settings_misc' ),
  319. );
  320. }
  321. $random_tip = array_rand( $tips );
  322. return $tips[ $random_tip ];
  323. }
  324. /**
  325. * Redirect to the welcome screen, if needed
  326. *
  327. * @since 1.14.0
  328. */
  329. public static function welcome_redirect() {
  330. // Redirect idea from Better Click To Tweet's welcome screen. Thanks Ben!
  331. if ( get_transient( 'pum_activation_redirect' ) ) {
  332. $do_redirect = true;
  333. $current_page = isset( $_GET['page'] ) ? wp_unslash( $_GET['page'] ) : false;
  334. // Bailout redirect during these events.
  335. if ( wp_doing_ajax() || is_network_admin() || ! current_user_can( 'manage_options' ) ) {
  336. $do_redirect = false;
  337. }
  338. // Bailout redirect on these pages & events.
  339. if ( 'pum-welcome' === $current_page || isset( $_GET['activate-multi'] ) ) {
  340. delete_transient( 'pum_activation_redirect' );
  341. $do_redirect = false;
  342. }
  343. if ( $do_redirect ) {
  344. delete_transient( 'pum_activation_redirect' );
  345. update_option( 'pum_seen_welcome', 1 );
  346. wp_safe_redirect( admin_url( 'admin.php?page=pum-welcome' ) );
  347. exit;
  348. }
  349. }
  350. }
  351. /**
  352. * Adds our welcome page to the dashboard
  353. *
  354. * @since 1.14.0
  355. */
  356. public static function set_up_welcome_page() {
  357. add_dashboard_page( '', '', 'manage_options', 'pum-welcome', array( __CLASS__, 'display_welcome_page' ) );
  358. }
  359. /**
  360. * Displays the contents for the welcome page
  361. *
  362. * @since 1.14.0
  363. */
  364. public static function display_welcome_page() {
  365. wp_enqueue_style( 'pum-admin-general' );
  366. $gravatar_url = get_avatar_url( 'danieliser@wizardinternetsolutions.com', array( 'size' => 60 ) );
  367. ?>
  368. <div class="pum-welcome-wrapper">
  369. <div>
  370. <h1>Welcome to Popup Maker!</h1>
  371. </div>
  372. <div>
  373. <p>Popup Maker was created to help us create effective popups on our own WordPress sites to boost our conversions. Now, over 4 years later, the plugin is installed on <strong>over 600,000 websites and has over 3,900 5-star reviews</strong>.</p>
  374. <p>There are a lot of ways you can use Popup Maker within your site including:</p>
  375. <ul>
  376. <li>Adding an auto-opening announcement popup</li>
  377. <li>Growing your email list with opt-in or lead magnet popups</li>
  378. <li>Increase order size by recommending products in a WooCommerce cross-sell popup</li>
  379. <li>Adding a content upgrade to your blog posts</li>
  380. <li>Greet a visitor from ProductHunt</li>
  381. <li>Reduce cart abandonment on your WooCommerce checkout page</li>
  382. <li>Adding post-sale WooCommerce surveys</li>
  383. <li>Using scroll-triggered popups to ask a site visitor if they have any questions</li>
  384. <li>And much more!</li>
  385. </ul>
  386. <p>Feel free to reach out if we can help with anything. We look forward to helping you increase your site’s conversions!</p>
  387. <div class="pum-welcome-signature">
  388. <img src="<?php echo esc_url( $gravatar_url ); ?>" alt="Daniel Iser, founder of Popup Maker">
  389. <p>~ Daniel and the Popup Maker team</p>
  390. </div>
  391. </div>
  392. <div class="pum-welcome-cta">
  393. <a class="button button-primary" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=popup' ) ); ?>">Create your first popup!</a>
  394. </div>
  395. </div>
  396. <?php
  397. }
  398. /**
  399. * Retrieves all dismissed pointers by user
  400. *
  401. * @param int|bool $user_id The ID of the user or false for current user.
  402. * @return array The array of pointer ID's that have been dimissed.
  403. * @since 1.11.0
  404. */
  405. private static function get_dismissed_pointers( $user_id = false ) {
  406. if ( false === $user_id ) {
  407. $user_id = get_current_user_id();
  408. }
  409. if ( 0 === intval( $user_id ) ) {
  410. return array();
  411. }
  412. $pointers = explode( ',', (string) get_user_meta( $user_id, 'dismissed_wp_pointers', true ) );
  413. if ( ! is_array( $pointers ) ) {
  414. return array();
  415. }
  416. return $pointers;
  417. }
  418. /**
  419. * Whether or not we should show tip alert
  420. *
  421. * @return bool True if the alert should be shown
  422. * @since 1.13.0
  423. */
  424. public static function should_show_tip() {
  425. return pum_is_admin_page() && current_user_can( 'manage_options' ) && strtotime( self::get_installed_on() . ' +3 days' ) < time() && ! self::has_turned_off_tips();
  426. }
  427. /**
  428. * Checks to see if site has turned off PM tips
  429. *
  430. * @return bool True if site has disabled tips
  431. * @since 1.13.0
  432. */
  433. public static function has_turned_off_tips() {
  434. return true === pum_get_option( 'disable_tips', false ) || 1 === intval( pum_get_option( 'disable_tips', false ) );
  435. }
  436. /**
  437. * Get the datetime string for when PM was installed.
  438. *
  439. * @return string
  440. * @since 1.13.0
  441. */
  442. public static function get_installed_on() {
  443. $installed_on = get_option( 'pum_installed_on', false );
  444. if ( ! $installed_on ) {
  445. $installed_on = current_time( 'mysql' );
  446. }
  447. return $installed_on;
  448. }
  449. /**
  450. * Ensures pointer is set up correctly.
  451. *
  452. * @param array $pointer The pointer.
  453. * @return bool
  454. * @since 1.11.0
  455. */
  456. private static function is_pointer_valid( $pointer ) {
  457. return ! empty( $pointer ) && ! empty( $pointer['pointer_id'] ) && ! empty( $pointer['target'] ) && ! empty( $pointer['options'] );
  458. }
  459. }