id . '_columns', array( $class, 'manage_columns' ) ); parent::__construct( array( 'plural' => $table_name, // Plural value used for labels and the objects being listed. 'singular' => $table_name, // Singular label for an object being listed, e.g. 'post'. 'ajax' => false, // If true, the parent class will call the _js_vars() method in the footer. ) ); } /** * Inits the module hooks. * * @return void * * @since 2.8.1 */ public static function hooks_init() { \add_action( 'admin_post_' . self::SWITCH_ACTION, array( Table_View::class, 'switch_action' ) ); \add_action( 'load-' . self::PAGE_SLUG, array( Table_View::class, 'page_load' ) ); \add_action( 'admin_post_' . self::UPDATE_ACTION, array( Table_View::class, 'update_table' ) ); \add_action( 'admin_post_' . self::INSERT_ACTION, array( Table_View::class, 'insert_table' ) ); } /** * Adds the module to the main plugin menu * * @return void * * @since 2.8.1 */ public static function menu_add() { $table_hook = \add_submenu_page( Logs_List::MENU_SLUG, ADVAN_INNER_NAME, \esc_html__( 'Table viewer', '0-day-analytics' ), 'manage_options', self::TABLE_MENU_SLUG, array( Table_View::class, 'analytics_table_page' ), 7 ); self::add_screen_options( $table_hook ); // \add_filter( 'manage_' . $table_hook . '_columns', array( Table_List::class, 'manage_columns' ) ); // Process bulk/table actions early on page load before any output. \add_action( 'load-' . $table_hook, array( __CLASS__, 'process_actions_load' ), 5 ); \add_action( 'load-' . $table_hook, array( Settings::class, 'aadvana_common_help' ) ); } /** * Runs table actions during the load- phase to avoid premature output. * * @return void * * @since 4.2.0 */ public static function process_actions_load() { if ( ! \is_user_logged_in() || ! \current_user_can( 'manage_options' ) ) { return; } $table_name = Common_Table::get_default_table(); $requested_table = isset( $_REQUEST['show_table'] ) ? \sanitize_key( \wp_unslash( $_REQUEST['show_table'] ) ) : ''; if ( $requested_table && \in_array( $requested_table, Common_Table::get_tables(), true ) ) { $table_name = $requested_table; } // Instantiate and process actions. Redirects will exit before any output. $table = new self( $table_name ); $table->handle_table_actions(); } /** * Prepares the list of items for displaying. * * Query, filter data, handle sorting, and pagination, and any other data-manipulation required prior to rendering * * @since 1.0.0 */ public function prepare_items() { $per_page = self::get_screen_option_per_page(); $current_page = $this->get_pagenum(); if ( 1 < $current_page ) { $offset = $per_page * ( $current_page - 1 ); } else { $offset = 0; } $wpdb_table = $this->get_table_name(); // Validate and allowlist orderby/order from request. $valid_columns = array_keys( self::$table::get_column_names_admin() ); $orderby = self::$table::get_real_id_name(); if ( isset( $_GET['orderby'] ) && '' !== trim( (string) $_GET['orderby'] ) ) { $requested_orderby = sanitize_key( \wp_unslash( (string) $_GET['orderby'] ) ); if ( in_array( $requested_orderby, $valid_columns, true ) ) { $orderby = $requested_orderby; } } $order = 'ASC'; if ( isset( $_GET['order'] ) && '' !== trim( (string) $_GET['order'] ) ) { $requested_order = strtoupper( (string) \sanitize_text_field( \wp_unslash( $_GET['order'] ) ) ); if ( in_array( $requested_order, array( 'ASC', 'DESC' ), true ) ) { $order = $requested_order; } } $items = $this->fetch_table_data( array( 'search_string' => self::escaped_search_input(), 'offset' => $offset, 'per_page' => $per_page, 'wpdb_table' => $wpdb_table, 'orderby' => $orderby, 'order' => $order, ) ); $columns = self::$table::manage_columns( array() ); $hidden = \get_user_option( 'manage' . WP_Helper::get_wp_screen()->id . 'columnshidden', false ); if ( ! $hidden ) { $hidden = array(); } $sortable = $this->get_sortable_columns(); $this->_column_headers = array( $columns, $hidden, $sortable ); $this->items = $items; // Set the pagination. $this->set_pagination_args( array( 'total_items' => $this->count, 'per_page' => self::get_screen_option_per_page(), 'total_pages' => ceil( $this->count / self::get_screen_option_per_page() ), ) ); } /** * Get a list of columns. The format is: * 'internal-name' => 'Title' * * @since 1.0.0 * * @return array */ public function get_columns() { return self::$table::manage_columns( array() ); } /** * Get a list of sortable columns. The format is: * 'internal-name' => 'orderby' * or * 'internal-name' => array( 'orderby', true ) * * The second format will make the initial sorting order be descending * * @since 1.1.0 * * @return array */ public function get_sortable_columns() { $first6_columns = array_keys( self::$table::get_column_names_admin() ); $sortable_columns = array(); /** * Actual sorting still needs to be done by prepare_items. * specify which columns should have the sort icon. * * The second bool param sets the column sort order - true ASC, false - DESC or unsorted. */ foreach ( $first6_columns as $value ) { $sortable_columns[ $value ] = array( $value, false ); } return $sortable_columns; } /** * Text displayed when no user data is available * * @since 1.0.0 * * @return void */ public function no_items() { \esc_html_e( 'No rows', '0-day-analytics' ); } /** * Fetch table data from the WordPress database. * * @param array $args - The arguments collected / passed. * * @since 1.0.0 * @since 3.8.0 - added $args param. * * @return array */ public function fetch_table_data( array $args = array() ) { global $wpdb; // Parse. $parsed_args = \wp_parse_args( $args, array( 'offset' => 0, 'search_string' => self::escaped_search_input(), 'per_page' => self::get_screen_option_per_page(), 'wpdb_table' => $this->get_table_name(), 'orderby' => self::$table::get_real_id_name(), 'order' => 'DESC', 'count' => false, ) ); self::$entity = self::$table; self::$default_order_by = self::$table::get_real_id_name(); $search_string = (string) \sanitize_text_field( \wp_unslash( $parsed_args['search_string'] ) ); $offset = max( 0, (int) $parsed_args['offset'] ); $per_page = max( 1, (int) $parsed_args['per_page'] ); $wpdb_table = (string) \sanitize_text_field( \wp_unslash( $parsed_args['wpdb_table'] ) ); // Allowlist orderby and order. $valid_columns = array_keys( self::$table::get_column_names_admin() ); $default_orderby = self::$table::get_real_id_name(); $orderby = in_array( (string) $parsed_args['orderby'], $valid_columns, true ) ? sanitize_key( \wp_unslash( (string) $parsed_args['orderby'] ) ) : $default_orderby; $order = strtoupper( (string) \sanitize_text_field( \wp_unslash( (string) $parsed_args['order'] ) ) ); $order = in_array( $order, array( 'ASC', 'DESC' ), true ) ? $order : 'DESC'; if ( ! Common_Table::check_table_exists( $wpdb_table ) ) { $this->count = 0; return array(); } $search_sql = ''; $order = self::get_order( $order ); $orderby = self::get_order_by( $orderby ); if ( '' !== $search_string ) { $like = '%' . $wpdb->esc_like( $search_string ) . '%'; $search_parts = array(); $search_parts[] = $wpdb->prepare( self::$table::get_real_id_name() . ' LIKE %s', $like ); foreach ( array_keys( self::$table::get_column_names_admin() ) as $value ) { $search_parts[] = $wpdb->prepare( "{$value} LIKE %s", $like ); } $search_sql = 'AND (' . implode( ' OR ', $search_parts ) . ') '; } $query = 'SELECT ' . implode( ', ', self::$table::get_column_names() ) . ' FROM ' . $wpdb_table . ' WHERE 1=1 ' . $search_sql . ' ORDER BY ' . $orderby . ' ' . $order; $query .= $wpdb->prepare( ' LIMIT %d OFFSET %d;', $per_page, $offset ); // query output_type will be an associative array with ARRAY_A. $query_results = $wpdb->get_results( $query, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $this->count = (int) $wpdb->get_var( 'SELECT COUNT(' . self::$table::get_real_id_name() . ') FROM ' . $wpdb_table . ' WHERE 1=1 ' . $search_sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared // return result array to prepare_items. return $query_results; } /** * Filter the table data based on the user search key * * @since 1.0.0 * * @param array $table_data - The data from the row. * @param string $search_key - The search key. * * @return array */ public function filter_table_data( $table_data, $search_key ) { $filtered_table_data = array_values( array_filter( $table_data, function( $row ) use ( $search_key ) { foreach ( $row as $row_val ) { if ( stripos( $row_val, $search_key ) !== false ) { return true; } } } ) ); return $filtered_table_data; } /** * Render a column when no column specific method exists. * * Use that method for common rendering and separate columns logic in different methods. See below. * * @param array $item - Array with the current row values. * @param string $column_name - The name of the currently processed column. * * @return mixed */ public function column_default( $item, $column_name ) { switch ( $column_name ) { default: return $this->common_column_render( $item, $column_name ); } } /** * Responsible for common column rendering * * @param array $item - The current riw with data. * @param string $column_name - The column name. * * @return string * * @since 2.1.0 */ private function common_column_render( array $item, $column_name ): string { if ( $column_name === self::$table::get_real_id_name() ) { $actions = array(); // View action is non-destructive; show to all viewers of this screen. $actions['view'] = '' . \esc_html__( 'View', '0-day-analytics' ) . ''; if ( \current_user_can( 'manage_options' ) ) { $query_args_view_data = array(); $query_args_view_data['_wpnonce'] = \wp_create_nonce( 'bulk-' . $this->_args['plural'] ); $delete_url = \add_query_arg( array( 'action' => 'delete', 'advan_' . self::$table::get_name() => $item[ self::$table::get_real_id_name() ], self::SEARCH_INPUT => self::escaped_search_input(), '_wpnonce' => $query_args_view_data['_wpnonce'], ) ); $actions['delete'] = '' . \esc_html__( 'Delete', '0-day-analytics' ) . ''; $edit_url = \remove_query_arg( array( 'updated', 'deleted' ), \add_query_arg( array( 'action' => 'edit_table_data', 'id' => $item[ self::$table::get_real_id_name() ], self::SEARCH_INPUT => self::escaped_search_input(), '_wpnonce' => \wp_create_nonce( 'edit-row' ), 'show_table' => self::$table::get_name(), ) ) ); $actions['edit'] = '' . \esc_html__( 'Edit', '0-day-analytics' ) . ''; } $row_value = \esc_html( $item[ $column_name ] ) . $this->row_actions( $actions ); } else { $len = \mb_strlen( (string) $item[ $column_name ] ); $value = \mb_substr( (string) $item[ $column_name ], 0, 100 ); // . '[…]' // Escape & wrap in tag. $row_value = '' . \esc_html( $value ) . ( ( 100 < $len ) ? '[…]' : '' ) . ''; // $row_value = \esc_html( $item[ $column_name ] ); } return $row_value; } /** * Get value for checkbox column. * * The special 'cb' column * * @param object $item - A row's data. * * @return string Text to be placed inside the column < td > . * * @since 2.1.0 */ protected function column_cb( $item ) { return sprintf( '' . '' ); } /** * Process actions triggered by the user * * @since 1.0.0 */ public function handle_table_actions() { /** * Note: Table bulk_actions can be identified by checking $_REQUEST['action'] and $_REQUEST['action2'] * * Action - is set if checkbox from top-most select-all is set, otherwise returns -1 * Action2 - is set if checkbox the bottom-most select-all checkbox is set, otherwise returns -1 */ if ( \is_user_logged_in() && \current_user_can( 'manage_options' ) ) { // check for individual row actions. $the_table_action = $this->current_action(); // check for table bulk actions. if ( ( isset( $_REQUEST['action'] ) && 'delete' === $_REQUEST['action'] ) || ( isset( $_REQUEST['action2'] ) && 'delete' === $_REQUEST['action2'] ) ) { // verify the nonce. /** * Note: the nonce field is set by the parent class * wp_nonce_field( 'bulk-' . $this->_args['plural'] ); */ WP_Helper::verify_admin_nonce( 'bulk-' . $this->_args['plural'] ); if ( isset( $_REQUEST[ 'advan_' . self::$table::get_name() ] ) ) { foreach ( (array) $_REQUEST[ 'advan_' . self::$table::get_name() ] as $id ) { self::$table::delete_by_id( (int) $id ); } } $redirect = \remove_query_arg( array( 'delete', '_wpnonce', 'advan_' . self::$table::get_name() ), \add_query_arg( array( self::SEARCH_INPUT => self::escaped_search_input(), 'paged' => $_REQUEST['paged'] ?? 1, 'page' => self::TABLE_MENU_SLUG, 'show_table' => self::$table::get_name(), ), \network_admin_url( 'admin.php' ) ) ); \wp_safe_redirect( $redirect ); exit; } } } /** * View a license information. * * @since 1.0.0 * * @param int $table_id - Record ID. */ public function page_view_data( $table_id ) { // Edit_Data::set_table( $this->table ); // Edit_Data::edit_record( $table_id ); } /** * Table navigation. * * @param string $which - Position of the nav. * * @since 1.1.0 */ public function extra_tablenav( $which ) { ?>
count > 0 ) { ?>
| | | | |
|