View file File name : Views.php Content :<?php namespace WPForms\Admin\Forms; use WP_Post; /** * List table views. * * @since 1.7.3 */ class Views { /** * Current view slug. * * @since 1.7.3 * * @var string */ private $current_view; /** * Views settings. * * @since 1.7.3 * * @var array */ private $views; /** * Count forms in different views. * * @since 1.7.3 * * @var array */ private $count; /** * Base URL. * * @since 1.7.3 * * @var string */ private $base_url; /** * Show form templates. * * @since 1.8.8 * * @var bool */ private $show_form_templates; /** * Views configuration. * * @since 1.7.3 */ private function configuration() { if ( ! empty( $this->views ) ) { return; } // Define views. $views = [ 'all' => [ 'title' => __( 'All', 'wpforms-lite' ), 'get_var' => '', 'get_var_value' => '', ], 'trash' => [ 'title' => __( 'Trash', 'wpforms-lite' ), 'get_var' => 'status', 'get_var_value' => 'trash', 'args' => [ 'post_status' => 'trash', ], ], ]; $this->show_form_templates = wpforms()->obj( 'forms_overview' )->overview_show_form_templates(); // Add Forms and Templates views if Show Templates setting is enabled. if ( $this->show_form_templates ) { $views = wpforms_array_insert( $views, [ 'forms' => [ 'title' => __( 'Forms', 'wpforms-lite' ), 'get_var' => 'type', 'get_var_value' => 'wpforms', 'args' => [ 'post_type' => 'wpforms', ], ], 'templates' => [ 'title' => __( 'Templates', 'wpforms-lite' ), 'get_var' => 'type', 'get_var_value' => 'wpforms-template', 'args' => [ 'post_type' => 'wpforms-template', ], ], ], 'all' ); } // phpcs:disable WPForms.Comments.ParamTagHooks.InvalidParamTagsQuantity /** * Filters configuration of the Forms Overview table views. * * @since 1.7.3 * * @param array $views { * Views array. * * @param array $view { * Each view is the array with three elements: * * @param string $title View title. * @param string $get_var URL query variable name. * @param string $get_var_value URL query variable value. * @param array $args Additional arguments to be passed to `wpforms()->obj( 'form' )->get()` method. * } * ... * } */ $this->views = apply_filters( 'wpforms_admin_forms_views_configuration', $views ); // phpcs:enable WPForms.Comments.ParamTagHooks.InvalidParamTagsQuantity } /** * Determine if the class is allowed to load. * * @since 1.7.3 * * @return bool */ private function allow_load(): bool { // Load only on the `All Forms` admin page. return wpforms_is_admin_page( 'overview' ); } /** * Initialize class. * * @since 1.7.3 */ public function init() { if ( ! $this->allow_load() ) { return; } $this->configuration(); $this->update_current_view(); $this->update_base_url(); $this->hooks(); } /** * Hooks. * * @since 1.7.3 */ private function hooks() { add_filter( 'wpforms_overview_table_update_count', [ $this, 'update_count' ], 10, 2 ); add_filter( 'wpforms_overview_table_update_count_all', [ $this, 'update_count' ], 10, 2 ); add_filter( 'wpforms_overview_table_prepare_items_args', [ $this, 'prepare_items_args' ], 100 ); add_filter( 'wpforms_overview_row_actions', [ $this, 'row_actions_all' ], 9, 2 ); add_filter( 'wpforms_overview_row_actions', [ $this, 'row_actions_trash' ], PHP_INT_MAX, 2 ); add_filter( 'wpforms_admin_forms_search_search_reset_block_message', [ $this, 'search_reset_message' ], 10, 4 ); } /** * Determine and save current view slug. * * @since 1.7.3 */ private function update_current_view() { if ( ! is_array( $this->views ) ) { return; } $this->current_view = 'all'; foreach ( $this->views as $slug => $view ) { if ( // phpcs:disable WordPress.Security.NonceVerification.Recommended isset( $_GET[ $view['get_var'] ] ) && $view['get_var_value'] === sanitize_key( $_GET[ $view['get_var'] ] ) // phpcs:enable WordPress.Security.NonceVerification.Recommended ) { $this->current_view = $slug; return; } } } /** * Update Base URL. * * @since 1.7.3 */ private function update_base_url() { if ( ! is_array( $this->views ) ) { return; } $get_vars = wp_list_pluck( $this->views, 'get_var' ); $get_vars = array_merge( $get_vars, [ 'paged', 'trashed', 'restored', 'deleted', 'duplicated', 'type', ] ); $this->base_url = remove_query_arg( $get_vars ); } /** * Get current view slug. * * @since 1.7.3 * * @return string */ public function get_current_view(): string { return $this->current_view; } /** * Get base URL. * * @since 1.7.5 * * @return string */ public function get_base_url(): string { return $this->base_url; } /** * Get view configuration by slug. * * @since 1.7.5 * * @param string $slug View slug. * * @return array */ public function get_view_by_slug( string $slug ): array { return $this->views[ $slug ] ?? []; // phpcs:ignore WPForms.Formatting.EmptyLineBeforeReturn.RemoveEmptyLineBeforeReturnStatement } /** * Update count. * * @since 1.7.3 * * @param array $count Number of forms in different views. * @param array $args Get forms arguments. * * @return array */ public function update_count( $count, $args ) { $defaults = [ 'nopaging' => true, 'no_found_rows' => true, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, 'fields' => 'ids', 'post_status' => 'publish', 'post_type' => wpforms()->obj( 'form' )::POST_TYPES, ]; $args = array_merge( $args, $defaults ); $count['all'] = $this->get_all_items_count( $args ); $count['trash'] = $this->get_trashed_forms_count( $args ); // Count forms and templates separately only if Show Templates screen setting is enabled. if ( $this->show_form_templates ) { $count['forms'] = $this->get_forms_count( $args ); $count['templates'] = $this->get_form_templates_count( $args ); } // Store in class property for further use. $this->count = $count; return $count; } /** * Get count of all items. * * May include only forms or both forms and form templates, depending on the * Screen Options settings whether to show form templates or not. * * @since 1.8.8 * * @param array $args Get forms arguments. * * @return int Number of forms and templates. */ private function get_all_items_count( array $args ): int { if ( ! $this->show_form_templates ) { $args['post_type'] = 'wpforms'; } $all_items = wpforms()->obj( 'form' )->get( '', $args ); return is_array( $all_items ) ? count( $all_items ) : 0; } /** * Get count of forms. * * @since 1.8.8 * * @param array $args Get forms arguments. * * @return int Number of published forms. */ private function get_forms_count( array $args ): int { $args['post_type'] = 'wpforms'; $forms = wpforms()->obj( 'form' )->get( '', $args ); return is_array( $forms ) ? count( $forms ) : 0; } /** * Get count of form templates. * * @since 1.8.8 * * @param array $args Get forms arguments. * * @return int Number of published templates. */ private function get_form_templates_count( array $args ): int { $args['post_type'] = 'wpforms-template'; $templates = wpforms()->obj( 'form' )->get( '', $args ); return is_array( $templates ) ? count( $templates ) : 0; } /** * Get count of trashed items. * * May include only forms or both forms and form templates, depending on the * Screen Options settings whether to show form templates or not. * * @since 1.8.8 * * @param array $args Get forms arguments. * * @return int Number of trashed forms. */ private function get_trashed_forms_count( array $args ): int { if ( ! $this->show_form_templates ) { $args['post_type'] = 'wpforms'; } $args['post_status'] = 'trash'; $forms = wpforms()->obj( 'form' )->get( '', $args ); return is_array( $forms ) ? count( $forms ) : 0; } /** * Get counts of forms in different views. * * @since 1.7.3 * * @return array */ public function get_count(): array { return $this->count; } /** * Prepare items arguments for list table. * * @since 1.8.8 * * @param array $args Get multiple forms arguments. * * @return array */ public function prepare_items_args( $args ): array { $view_args = $this->views[ $this->current_view ]['args'] ?? []; if ( ! empty( $view_args ) ) { $args = array_merge( $args, $view_args ); } return $args; } /** * Get forms from Trash when preparing items for list table. * * @since 1.7.3 * * @depecated 1.8.8 The `prepare_items_args()` now handles all cases, uses `$this->views`. * * @param array $args Get multiple forms arguments. * * @return array */ public function prepare_items_trash( $args ) { _deprecated_function( __METHOD__, '1.8.8 of the WPForms plugin' ); return $args; } /** * Generate views items. * * @since 1.7.3 * * @return array */ public function get_views(): array { if ( ! is_array( $this->views ) ) { return []; } $views = []; foreach ( $this->views as $slug => $view ) { if ( $slug === 'trash' && $this->current_view !== 'trash' && empty( $this->count[ $slug ] ) ) { continue; } $views[ $slug ] = $this->get_view_markup( $slug ); } /** * Filters the Forms Overview table views links. * * @since 1.7.3 * * @param array $views Views links. * @param array $count Count forms in different views. */ return apply_filters( 'wpforms_admin_forms_views_get_views', $views, $this->count ); } /** * Generate single view item. * * @since 1.7.3 * * @param string $slug View slug. * * @return string */ private function get_view_markup( string $slug ): string { if ( empty( $this->views[ $slug ] ) ) { return ''; } $view = $this->views[ $slug ]; return sprintf( '<a href="%1$s"%2$s>%3$s <span class="count">(%4$d)</span></a>', $slug === 'all' ? esc_url( $this->base_url ) : esc_url( add_query_arg( $view['get_var'], $view['get_var_value'], $this->base_url ) ), $this->current_view === $slug ? ' class="current"' : '', esc_html( $view['title'] ), empty( $this->count[ $slug ] ) ? 0 : absint( $this->count[ $slug ] ) ); } /** * Row actions for views "All", "Forms", "Templates". * * @since 1.7.3 * * @param array $row_actions Row actions. * @param WP_Post $form Form object. * * @return array */ public function row_actions_all( $row_actions, $form ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh // Modify row actions only for these views. $allowed_views = [ 'all', 'forms', 'templates' ]; if ( ! in_array( $this->current_view, $allowed_views, true ) ) { return $row_actions; } $is_form_template = wpforms_is_form_template( $form ); $row_actions = []; // Edit. if ( wpforms_current_user_can( 'edit_form_single', $form->ID ) ) { $row_actions['edit'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( add_query_arg( [ 'view' => 'fields', 'form_id' => $form->ID, ], admin_url( 'admin.php?page=wpforms-builder' ) ) ), $is_form_template ? esc_attr__( 'Edit this template', 'wpforms-lite' ) : esc_attr__( 'Edit this form', 'wpforms-lite' ), esc_html__( 'Edit', 'wpforms-lite' ) ); } // Entries. if ( wpforms_current_user_can( 'view_entries_form_single', $form->ID ) ) { $row_actions['entries'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( add_query_arg( [ 'view' => 'list', 'form_id' => $form->ID, ], admin_url( 'admin.php?page=wpforms-entries' ) ) ), esc_attr__( 'View entries', 'wpforms-lite' ), esc_html__( 'Entries', 'wpforms-lite' ) ); } // Payments. if ( wpforms_current_user_can( wpforms_get_capability_manage_options(), $form->ID ) && wpforms()->obj( 'payment' )->get_by( 'form_id', $form->ID ) ) { $row_actions['payments'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( add_query_arg( [ 'page' => 'wpforms-payments', 'form_id' => $form->ID, ], admin_url( 'admin.php' ) ) ), esc_attr__( 'View payments', 'wpforms-lite' ), esc_html__( 'Payments', 'wpforms-lite' ) ); } // Preview. if ( wpforms_current_user_can( 'view_form_single', $form->ID ) ) { $row_actions['preview_'] = sprintf( '<a href="%s" title="%s" target="_blank" rel="noopener noreferrer">%s</a>', esc_url( wpforms_get_form_preview_url( $form->ID ) ), esc_attr__( 'View preview', 'wpforms-lite' ), esc_html__( 'Preview', 'wpforms-lite' ) ); } // Duplicate. if ( wpforms_current_user_can( 'create_forms' ) && wpforms_current_user_can( 'view_form_single', $form->ID ) ) { $row_actions['duplicate'] = sprintf( '<a href="%1$s" title="%2$s" data-type="%3$s">%4$s</a>', esc_url( wp_nonce_url( add_query_arg( [ 'action' => 'duplicate', 'form_id' => $form->ID, ], $this->base_url ), 'wpforms_duplicate_form_nonce' ) ), $is_form_template ? esc_attr__( 'Duplicate this template', 'wpforms-lite' ) : esc_attr__( 'Duplicate this form', 'wpforms-lite' ), $is_form_template ? 'template' : 'form', esc_html__( 'Duplicate', 'wpforms-lite' ) ); } // Trash. if ( wpforms_current_user_can( 'delete_form_single', $form->ID ) ) { $query_arg = [ 'action' => 'trash', 'form_id' => $form->ID, ]; if ( $this->current_view !== 'all' ) { $query_arg['type'] = $this->current_view === 'templates' ? 'wpforms-template' : 'wpforms'; } $row_actions['trash'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( wp_nonce_url( add_query_arg( $query_arg, $this->base_url ), 'wpforms_trash_form_nonce' ) ), $is_form_template ? esc_attr__( 'Move this form template to trash', 'wpforms-lite' ) : esc_attr__( 'Move this form to trash', 'wpforms-lite' ), esc_html__( 'Trash', 'wpforms-lite' ) ); } return $row_actions; } /** * Row actions for view "Trash". * * @since 1.7.3 * * @param array $row_actions Row actions. * @param WP_Post $form Form object. * * @return array */ public function row_actions_trash( $row_actions, $form ) { if ( $this->current_view !== 'trash' || ! wpforms_current_user_can( 'delete_form_single', $form->ID ) ) { return $row_actions; } $is_form_template = wpforms_is_form_template( $form ); $row_actions = []; // Restore form. $row_actions['restore'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( wp_nonce_url( add_query_arg( [ 'action' => 'restore', 'form_id' => $form->ID, 'status' => 'trash', ], $this->base_url ), 'wpforms_restore_form_nonce' ) ), $is_form_template ? esc_attr__( 'Restore this template', 'wpforms-lite' ) : esc_attr__( 'Restore this form', 'wpforms-lite' ), esc_html__( 'Restore', 'wpforms-lite' ) ); // Delete permanently. $row_actions['delete'] = sprintf( '<a href="%1$s" title="%2$s" data-type="%3$s">%4$s</a>', esc_url( wp_nonce_url( add_query_arg( [ 'action' => 'delete', 'form_id' => $form->ID, 'status' => 'trash', ], $this->base_url ), 'wpforms_delete_form_nonce' ) ), $is_form_template ? esc_attr__( 'Delete this template permanently', 'wpforms-lite' ) : esc_attr__( 'Delete this form permanently', 'wpforms-lite' ), $is_form_template ? 'template' : 'form', esc_html__( 'Delete Permanently', 'wpforms-lite' ) ); return $row_actions; } /** * Search reset message. * * @since 1.7.3 * * @param string $message Search reset block message. * @param string $search_term Search term. * @param array $count Count forms in different views. * @param string $current_view Current view. * * @return string */ public function search_reset_message( $message, $search_term, $count, $current_view ) { if ( $current_view !== 'trash' ) { return $message; } $count['trash'] = ! empty( $count['trash'] ) ? $count['trash'] : 0; return sprintf( wp_kses( /* translators: %1$d - number of forms found in the trash, %2$s - search term. */ _n( 'Found <strong>%1$d form</strong> in <em>the trash</em> containing <em>"%2$s"</em>', 'Found <strong>%1$d forms</strong> in <em>the trash</em> containing <em>"%2$s"</em>', (int) $count['trash'], 'wpforms-lite' ), [ 'strong' => [], 'em' => [], ] ), (int) $count['trash'], esc_html( $search_term ) ); } /** * Extra controls to be displayed between bulk actions and pagination. * * @since 1.7.3 * * @param string $which The location of the table navigation: 'top' or 'bottom'. */ public function extra_tablenav( $which ) { if ( ! wpforms_current_user_can( 'delete_form_single' ) ) { return; } if ( $this->current_view !== 'trash' ) { return; } // Preserve current view after applying bulk action. echo '<input type="hidden" name="status" value="trash">'; // Display Empty Trash button. printf( '<a href="%1$s" class="button delete-all">%2$s</a>', esc_url( wp_nonce_url( add_query_arg( [ 'action' => 'empty_trash', 'form_id' => 1, // Technically, `empty_trash` is one of the bulk actions, therefore we need to provide fake form_id to proceed. 'status' => 'trash', ], $this->base_url ), 'wpforms_empty_trash_form_nonce' ) ), esc_html__( 'Empty Trash', 'wpforms-lite' ) ); } }