Нет описания

class-wc-admin-pointers.php 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <?php
  2. /**
  3. * Adds and controls pointers for contextual help/tutorials
  4. *
  5. * @package WooCommerce\Admin\Pointers
  6. * @version 2.4.0
  7. */
  8. if ( ! defined( 'ABSPATH' ) ) {
  9. exit;
  10. }
  11. /**
  12. * WC_Admin_Pointers Class.
  13. */
  14. class WC_Admin_Pointers {
  15. /**
  16. * Constructor.
  17. */
  18. public function __construct() {
  19. add_action( 'admin_enqueue_scripts', array( $this, 'setup_pointers_for_screen' ) );
  20. }
  21. /**
  22. * Setup pointers for screen.
  23. */
  24. public function setup_pointers_for_screen() {
  25. $screen = get_current_screen();
  26. if ( ! $screen ) {
  27. return;
  28. }
  29. switch ( $screen->id ) {
  30. case 'product':
  31. $this->create_product_tutorial();
  32. break;
  33. }
  34. }
  35. /**
  36. * Pointers for creating a product.
  37. */
  38. public function create_product_tutorial() {
  39. if ( ! isset( $_GET['tutorial'] ) || ! current_user_can( 'manage_options' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
  40. return;
  41. }
  42. // These pointers will chain - they will not be shown at once.
  43. $pointers = array(
  44. 'pointers' => array(
  45. 'title' => array(
  46. 'target' => '#title',
  47. 'next' => 'content',
  48. 'next_trigger' => array(
  49. 'target' => '#title',
  50. 'event' => 'input',
  51. ),
  52. 'options' => array(
  53. 'content' => '<h3>' . esc_html__( 'Product name', 'woocommerce' ) . '</h3>' .
  54. '<p>' . esc_html__( 'Give your new product a name here. This is a required field and will be what your customers will see in your store.', 'woocommerce' ) . '</p>',
  55. 'position' => array(
  56. 'edge' => 'top',
  57. 'align' => 'left',
  58. ),
  59. ),
  60. ),
  61. 'content' => array(
  62. 'target' => '#wp-content-editor-container',
  63. 'next' => 'product-type',
  64. 'next_trigger' => array(),
  65. 'options' => array(
  66. 'content' => '<h3>' . esc_html__( 'Product description', 'woocommerce' ) . '</h3>' .
  67. '<p>' . esc_html__( 'This is your products main body of content. Here you should describe your product in detail.', 'woocommerce' ) . '</p>',
  68. 'position' => array(
  69. 'edge' => 'bottom',
  70. 'align' => 'middle',
  71. ),
  72. ),
  73. ),
  74. 'product-type' => array(
  75. 'target' => '#product-type',
  76. 'next' => 'virtual',
  77. 'next_trigger' => array(
  78. 'target' => '#product-type',
  79. 'event' => 'change blur click',
  80. ),
  81. 'options' => array(
  82. 'content' => '<h3>' . esc_html__( 'Choose product type', 'woocommerce' ) . '</h3>' .
  83. '<p>' . esc_html__( 'Choose a type for this product. Simple is suitable for most physical goods and services (we recommend setting up a simple product for now).', 'woocommerce' ) . '</p>' .
  84. '<p>' . esc_html__( 'Variable is for more complex products such as t-shirts with multiple sizes.', 'woocommerce' ) . '</p>' .
  85. '<p>' . esc_html__( 'Grouped products are for grouping several simple products into one.', 'woocommerce' ) . '</p>' .
  86. '<p>' . esc_html__( 'Finally, external products are for linking off-site.', 'woocommerce' ) . '</p>',
  87. 'position' => array(
  88. 'edge' => 'bottom',
  89. 'align' => 'middle',
  90. ),
  91. ),
  92. ),
  93. 'virtual' => array(
  94. 'target' => '#_virtual',
  95. 'next' => 'downloadable',
  96. 'next_trigger' => array(
  97. 'target' => '#_virtual',
  98. 'event' => 'change',
  99. ),
  100. 'options' => array(
  101. 'content' => '<h3>' . esc_html__( 'Virtual products', 'woocommerce' ) . '</h3>' .
  102. '<p>' . esc_html__( 'Check the "Virtual" box if this is a non-physical item, for example a service, which does not need shipping.', 'woocommerce' ) . '</p>',
  103. 'position' => array(
  104. 'edge' => 'bottom',
  105. 'align' => 'middle',
  106. ),
  107. ),
  108. ),
  109. 'downloadable' => array(
  110. 'target' => '#_downloadable',
  111. 'next' => 'regular_price',
  112. 'next_trigger' => array(
  113. 'target' => '#_downloadable',
  114. 'event' => 'change',
  115. ),
  116. 'options' => array(
  117. 'content' => '<h3>' . esc_html__( 'Downloadable products', 'woocommerce' ) . '</h3>' .
  118. '<p>' . esc_html__( 'If purchasing this product gives a customer access to a downloadable file, e.g. software, check this box.', 'woocommerce' ) . '</p>',
  119. 'position' => array(
  120. 'edge' => 'bottom',
  121. 'align' => 'middle',
  122. ),
  123. ),
  124. ),
  125. 'regular_price' => array(
  126. 'target' => '#_regular_price',
  127. 'next' => 'postexcerpt',
  128. 'next_trigger' => array(
  129. 'target' => '#_regular_price',
  130. 'event' => 'input',
  131. ),
  132. 'options' => array(
  133. 'content' => '<h3>' . esc_html__( 'Prices', 'woocommerce' ) . '</h3>' .
  134. '<p>' . esc_html__( 'Next you need to give your product a price.', 'woocommerce' ) . '</p>',
  135. 'position' => array(
  136. 'edge' => 'bottom',
  137. 'align' => 'middle',
  138. ),
  139. ),
  140. ),
  141. 'postexcerpt' => array(
  142. 'target' => '#postexcerpt',
  143. 'next' => 'postimagediv',
  144. 'next_trigger' => array(
  145. 'target' => '#postexcerpt',
  146. 'event' => 'input',
  147. ),
  148. 'options' => array(
  149. 'content' => '<h3>' . esc_html__( 'Product short description', 'woocommerce' ) . '</h3>' .
  150. '<p>' . esc_html__( 'Add a quick summary for your product here. This will appear on the product page under the product name.', 'woocommerce' ) . '</p>',
  151. 'position' => array(
  152. 'edge' => 'bottom',
  153. 'align' => 'middle',
  154. ),
  155. ),
  156. ),
  157. 'postimagediv' => array(
  158. 'target' => '#postimagediv',
  159. 'next' => 'product_tag',
  160. 'options' => array(
  161. 'content' => '<h3>' . esc_html__( 'Product images', 'woocommerce' ) . '</h3>' .
  162. '<p>' . esc_html__( "Upload or assign an image to your product here. This image will be shown in your store's catalog.", 'woocommerce' ) . '</p>',
  163. 'position' => array(
  164. 'edge' => 'right',
  165. 'align' => 'middle',
  166. ),
  167. ),
  168. ),
  169. 'product_tag' => array(
  170. 'target' => '#tagsdiv-product_tag',
  171. 'next' => 'product_catdiv',
  172. 'options' => array(
  173. 'content' => '<h3>' . esc_html__( 'Product tags', 'woocommerce' ) . '</h3>' .
  174. '<p>' . esc_html__( 'You can optionally "tag" your products here. Tags are a method of labeling your products to make them easier for customers to find.', 'woocommerce' ) . '</p>',
  175. 'position' => array(
  176. 'edge' => 'right',
  177. 'align' => 'middle',
  178. ),
  179. ),
  180. ),
  181. 'product_catdiv' => array(
  182. 'target' => '#product_catdiv',
  183. 'next' => 'submitdiv',
  184. 'options' => array(
  185. 'content' => '<h3>' . esc_html__( 'Product categories', 'woocommerce' ) . '</h3>' .
  186. '<p>' . esc_html__( 'Optionally assign categories to your products to make them easier to browse through and find in your store.', 'woocommerce' ) . '</p>',
  187. 'position' => array(
  188. 'edge' => 'right',
  189. 'align' => 'middle',
  190. ),
  191. ),
  192. ),
  193. 'submitdiv' => array(
  194. 'target' => '#submitdiv',
  195. 'next' => '',
  196. 'options' => array(
  197. 'content' => '<h3>' . esc_html__( 'Publish your product!', 'woocommerce' ) . '</h3>' .
  198. '<p>' . esc_html__( 'When you are finished editing your product, hit the "Publish" button to publish your product to your store.', 'woocommerce' ) . '</p>',
  199. 'position' => array(
  200. 'edge' => 'right',
  201. 'align' => 'middle',
  202. ),
  203. ),
  204. ),
  205. ),
  206. );
  207. $this->enqueue_pointers( $pointers );
  208. }
  209. /**
  210. * Enqueue pointers and add script to page.
  211. *
  212. * @param array $pointers Pointers data.
  213. */
  214. public function enqueue_pointers( $pointers ) {
  215. $pointers = rawurlencode( wp_json_encode( $pointers ) );
  216. wp_enqueue_style( 'wp-pointer' );
  217. wp_enqueue_script( 'wp-pointer' );
  218. wc_enqueue_js(
  219. "jQuery( function( $ ) {
  220. var wc_pointers = JSON.parse( decodeURIComponent( '{$pointers}' ) );
  221. setTimeout( init_wc_pointers, 800 );
  222. function init_wc_pointers() {
  223. $.each( wc_pointers.pointers, function( i ) {
  224. show_wc_pointer( i );
  225. return false;
  226. });
  227. }
  228. function show_wc_pointer( id ) {
  229. var pointer = wc_pointers.pointers[ id ];
  230. var options = $.extend( pointer.options, {
  231. pointerClass: 'wp-pointer wc-pointer',
  232. close: function() {
  233. if ( pointer.next ) {
  234. show_wc_pointer( pointer.next );
  235. }
  236. },
  237. buttons: function( event, t ) {
  238. var close = '" . esc_js( __( 'Dismiss', 'woocommerce' ) ) . "',
  239. next = '" . esc_js( __( 'Next', 'woocommerce' ) ) . "',
  240. button = $( '<a class=\"close\" href=\"#\">' + close + '</a>' ),
  241. button2 = $( '<a class=\"button button-primary\" href=\"#\">' + next + '</a>' ),
  242. wrapper = $( '<div class=\"wc-pointer-buttons\" />' );
  243. button.on( 'click.pointer', function(e) {
  244. e.preventDefault();
  245. t.element.pointer('destroy');
  246. });
  247. button2.on( 'click.pointer', function(e) {
  248. e.preventDefault();
  249. t.element.pointer('close');
  250. });
  251. wrapper.append( button );
  252. wrapper.append( button2 );
  253. return wrapper;
  254. },
  255. } );
  256. var this_pointer = $( pointer.target ).pointer( options );
  257. this_pointer.pointer( 'open' );
  258. if ( pointer.next_trigger ) {
  259. $( pointer.next_trigger.target ).on( pointer.next_trigger.event, function() {
  260. setTimeout( function() { this_pointer.pointer( 'close' ); }, 400 );
  261. });
  262. }
  263. }
  264. });"
  265. );
  266. }
  267. }
  268. new WC_Admin_Pointers();