Нет описания

class-overview.php 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <?php
  2. /**
  3. * Primary overview page inside the admin which lists all forms.
  4. *
  5. * @since 1.0.0
  6. */
  7. class WPForms_Overview {
  8. /**
  9. * Primary class constructor.
  10. *
  11. * @since 1.0.0
  12. */
  13. public function __construct() {
  14. // Maybe load overview page.
  15. add_action( 'admin_init', array( $this, 'init' ) );
  16. // Setup screen options. Needs to be here as admin_init hook it too late.
  17. add_action( 'load-toplevel_page_wpforms-overview', array( $this, 'screen_options' ) );
  18. add_filter( 'set-screen-option', array( $this, 'screen_options_set' ), 10, 3 );
  19. add_filter( 'set_screen_option_wpforms_forms_per_page', [ $this, 'screen_options_set' ], 10, 3 );
  20. }
  21. /**
  22. * Determine if the user is viewing the overview page, if so, party on.
  23. *
  24. * @since 1.0.0
  25. */
  26. public function init() {
  27. // Only load if we are actually on the overview page.
  28. if ( ! wpforms_is_admin_page( 'overview' ) ) {
  29. return;
  30. }
  31. // Bulk actions.
  32. add_action( 'load-toplevel_page_wpforms-overview', array( $this, 'notices' ) );
  33. add_action( 'load-toplevel_page_wpforms-overview', array( $this, 'process_bulk_actions' ) );
  34. add_filter( 'removable_query_args', array( $this, 'removable_query_args' ) );
  35. // The overview page leverages WP_List_Table so we must load it.
  36. if ( ! class_exists( 'WP_List_Table', false ) ) {
  37. require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
  38. }
  39. // Load the class that builds the overview table.
  40. require_once WPFORMS_PLUGIN_DIR . 'includes/admin/overview/class-overview-table.php';
  41. add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
  42. add_action( 'wpforms_admin_page', array( $this, 'output' ) );
  43. // Provide hook for addons.
  44. do_action( 'wpforms_overview_init' );
  45. }
  46. /**
  47. * Add per-page screen option to the Forms table.
  48. *
  49. * @since 1.0.0
  50. */
  51. public function screen_options() {
  52. $screen = get_current_screen();
  53. if ( null === $screen || 'toplevel_page_wpforms-overview' !== $screen->id ) {
  54. return;
  55. }
  56. add_screen_option(
  57. 'per_page',
  58. array(
  59. 'label' => esc_html__( 'Number of forms per page:', 'wpforms-lite' ),
  60. 'option' => 'wpforms_forms_per_page',
  61. 'default' => apply_filters( 'wpforms_overview_per_page', 20 ),
  62. )
  63. );
  64. }
  65. /**
  66. * Form table per-page screen option value.
  67. *
  68. * @since 1.0.0
  69. *
  70. * @param bool $keep Whether to save or skip saving the screen option value. Default false.
  71. * @param string $option The option name.
  72. * @param int $value The number of rows to use.
  73. *
  74. * @return mixed
  75. */
  76. public function screen_options_set( $keep, $option, $value ) {
  77. if ( 'wpforms_forms_per_page' === $option ) {
  78. return $value;
  79. }
  80. return $keep;
  81. }
  82. /**
  83. * Enqueue assets for the overview page.
  84. *
  85. * @since 1.0.0
  86. */
  87. public function enqueues() {
  88. // Hook for addons.
  89. do_action( 'wpforms_overview_enqueue' );
  90. }
  91. /**
  92. * Build the output for the overview page.
  93. *
  94. * @since 1.0.0
  95. */
  96. public function output() {
  97. ?>
  98. <div id="wpforms-overview" class="wrap wpforms-admin-wrap">
  99. <h1 class="page-title">
  100. <?php esc_html_e( 'Forms Overview', 'wpforms-lite' ); ?>
  101. <?php if ( wpforms_current_user_can( 'create_forms' ) ) : ?>
  102. <a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-builder&view=setup' ) ); ?>" class="add-new-h2 wpforms-btn-orange">
  103. <?php esc_html_e( 'Add New', 'wpforms-lite' ); ?>
  104. </a>
  105. <?php endif; ?>
  106. </h1>
  107. <?php
  108. $overview_table = new WPForms_Overview_Table();
  109. $overview_table->prepare_items();
  110. ?>
  111. <div class="wpforms-admin-content">
  112. <?php
  113. do_action( 'wpforms_admin_overview_before_table' );
  114. if ( empty( $overview_table->items ) ) {
  115. // Output no forms screen.
  116. echo wpforms_render( 'admin/empty-states/no-forms' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
  117. } else {
  118. ?>
  119. <form id="wpforms-overview-table" method="get" action="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-overview' ) ); ?>">
  120. <input type="hidden" name="post_type" value="wpforms" />
  121. <input type="hidden" name="page" value="wpforms-overview" />
  122. <?php $overview_table->views(); ?>
  123. <?php $overview_table->display(); ?>
  124. </form>
  125. <?php } ?>
  126. </div>
  127. </div>
  128. <?php
  129. }
  130. /**
  131. * Add admin action notices and process bulk actions.
  132. *
  133. * @since 1.5.7
  134. */
  135. public function notices() {
  136. $deleted = ! empty( $_REQUEST['deleted'] ) ? sanitize_key( $_REQUEST['deleted'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification
  137. $duplicated = ! empty( $_REQUEST['duplicated'] ) ? sanitize_key( $_REQUEST['duplicated'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification
  138. $notice = array();
  139. if ( $deleted && 'error' !== $deleted ) {
  140. $notice = array(
  141. 'type' => 'info',
  142. /* translators: %s - Deleted forms count. */
  143. 'msg' => sprintf( _n( '%s form was successfully deleted.', '%s forms were successfully deleted.', $deleted, 'wpforms-lite' ), $deleted ),
  144. );
  145. }
  146. if ( $duplicated && 'error' !== $duplicated ) {
  147. $notice = array(
  148. 'type' => 'info',
  149. /* translators: %s - Duplicated forms count. */
  150. 'msg' => sprintf( _n( '%s form was successfully duplicated.', '%s forms were successfully duplicated.', $duplicated, 'wpforms-lite' ), $duplicated ),
  151. );
  152. }
  153. if ( 'error' === $deleted || 'error' === $duplicated ) {
  154. $notice = array(
  155. 'type' => 'error',
  156. 'msg' => esc_html__( 'Security check failed. Please try again.', 'wpforms-lite' ),
  157. );
  158. }
  159. if ( ! empty( $notice ) ) {
  160. \WPForms\Admin\Notice::add( $notice['msg'], $notice['type'] );
  161. }
  162. }
  163. /**
  164. * Process the bulk table actions.
  165. *
  166. * @since 1.5.7
  167. */
  168. public function process_bulk_actions() {
  169. $ids = isset( $_GET['form_id'] ) ? array_map( 'absint', (array) $_GET['form_id'] ) : array(); // phpcs:ignore WordPress.Security.NonceVerification
  170. $action = ! empty( $_REQUEST['action'] ) ? sanitize_key( $_REQUEST['action'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification
  171. if ( $action === '-1' ) {
  172. $action = ! empty( $_REQUEST['action2'] ) ? sanitize_key( $_REQUEST['action2'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification
  173. }
  174. // Checking the sortable column link.
  175. $is_orderby_link = ! empty( $_REQUEST['orderby'] ) && ! empty( $_REQUEST['order'] );
  176. if ( empty( $ids ) || empty( $action ) || $is_orderby_link ) {
  177. return;
  178. }
  179. // Check exact action values.
  180. if ( ! in_array( $action, [ 'delete', 'duplicate' ], true ) ) {
  181. return;
  182. }
  183. if ( empty( $_GET['_wpnonce'] ) ) {
  184. return;
  185. }
  186. // Check the nonce.
  187. if (
  188. ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'bulk-forms' ) &&
  189. ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'wpforms_' . $action . '_form_nonce' )
  190. ) {
  191. return;
  192. }
  193. // Check that we have a method for this action.
  194. if ( ! method_exists( $this, 'bulk_action_' . $action . '_forms' ) ) {
  195. return;
  196. }
  197. $processed_forms = count( $this->{'bulk_action_' . $action . '_forms'}( $ids ) );
  198. // Unset get vars and perform redirect to avoid action reuse.
  199. wp_safe_redirect(
  200. add_query_arg(
  201. $action . 'd',
  202. $processed_forms,
  203. remove_query_arg( array( 'action', 'action2', '_wpnonce', 'form_id', 'paged', '_wp_http_referer' ) )
  204. )
  205. );
  206. exit;
  207. }
  208. /**
  209. * Delete forms.
  210. *
  211. * @since 1.5.7
  212. *
  213. * @param array $ids Form ids to delete.
  214. *
  215. * @return array List of deleted forms.
  216. */
  217. private function bulk_action_delete_forms( $ids ) {
  218. if ( ! is_array( $ids ) ) {
  219. return [];
  220. }
  221. $deleted = [];
  222. foreach ( $ids as $id ) {
  223. $deleted[ $id ] = wpforms()->form->delete( $id );
  224. }
  225. return array_keys( array_filter( $deleted ) );
  226. }
  227. /**
  228. * Duplicate forms.
  229. *
  230. * @since 1.5.7
  231. *
  232. * @param array $ids Form ids to duplicate.
  233. *
  234. * @return array List of duplicated forms.
  235. */
  236. private function bulk_action_duplicate_forms( $ids ) {
  237. if ( ! is_array( $ids ) ) {
  238. return [];
  239. }
  240. if ( ! wpforms_current_user_can( 'create_forms' ) ) {
  241. return [];
  242. }
  243. $duplicated = [];
  244. foreach ( $ids as $id ) {
  245. if ( wpforms_current_user_can( 'view_form_single', $id ) ) {
  246. $duplicated[ $id ] = wpforms()->form->duplicate( $id );
  247. }
  248. }
  249. return array_keys( array_filter( $duplicated ) );
  250. }
  251. /**
  252. * Remove certain arguments from a query string that WordPress should always hide for users.
  253. *
  254. * @since 1.5.7
  255. *
  256. * @param array $removable_query_args An array of parameters to remove from the URL.
  257. *
  258. * @return array Extended/filtered array of parameters to remove from the URL.
  259. */
  260. public function removable_query_args( $removable_query_args ) {
  261. if ( wpforms_is_admin_page( 'overview' ) ) {
  262. $removable_query_args[] = 'duplicated';
  263. }
  264. return $removable_query_args;
  265. }
  266. }
  267. new WPForms_Overview();