post_type ); // Create nonce for the edit links $new_nonce = AI_Editor_Nonce_Manager::create_nonce( AI_Editor_Nonce_Manager::NAVIGATION_ACTION ); // Build query args $query_args = array(); // Only add non-default parameters to keep URLs clean if ( 'page' === $post->post_type ) { // For pages, menu_order ASC is default if ( 'menu_order' !== $sort_params['orderby'] || 'ASC' !== $sort_params['order'] ) { if ( 'menu_order' !== $sort_params['orderby'] ) { $query_args['orderby'] = $sort_params['orderby']; } if ( 'ASC' !== $sort_params['order'] ) { $query_args['order'] = $sort_params['order']; } } } else { // For other post types, date DESC is default if ( 'date' !== $sort_params['orderby'] || 'DESC' !== $sort_params['order'] ) { if ( 'date' !== $sort_params['orderby'] ) { $query_args['orderby'] = $sort_params['orderby']; } if ( 'DESC' !== $sort_params['order'] ) { $query_args['order'] = $sort_params['order']; } } } // Add post status if not 'all' if ( ! empty( $sort_params['post_status'] ) && 'all' !== $sort_params['post_status'] ) { $query_args['post_status'] = $sort_params['post_status']; } // Always add nonce $query_args[ AI_Editor_Nonce_Manager::NAVIGATION_NONCE ] = $new_nonce; // Only modify the edit link if we have parameters to add if ( ! empty( $query_args ) ) { $query = http_build_query( $query_args ); $actions['edit'] = preg_replace( '/href="([^"]+)"/', 'href="$1&' . $query . '"', $actions['edit'] ); } return $actions; } /** * Get sort parameters from admin screen * * @param string $post_type Current post type. * @return array Sort parameters. */ function ai_editor_get_admin_sort_params( $post_type ) { // Set default values based on post type if ( 'page' === $post_type ) { $default_orderby = 'menu_order'; $default_order = 'ASC'; } elseif ( 'product' === $post_type ) { // WooCommerce products often default to menu_order too $default_orderby = 'menu_order'; $default_order = 'ASC'; } else { $default_orderby = 'date'; $default_order = 'DESC'; } $orderby = $default_orderby; $order = $default_order; $post_status = 'all'; // Get current screen to check if we're on the right admin page $screen = get_current_screen(); if ( ! $screen || 'edit' !== $screen->base || $screen->post_type !== $post_type ) { return array( 'orderby' => $orderby, 'order' => $order, 'post_status' => $post_status, ); } // Check if this is a valid admin request // Note: We don't need nonce verification here as we're just reading the current list view state // The WordPress admin already handles security for the list table // Get and sanitize URL parameters // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading admin list state, not processing form if ( isset( $_GET['orderby'] ) ) { $allowed_fields = array( 'menu_order', 'title', 'date', 'modified', 'author', 'ID' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading admin list state $temp_orderby = sanitize_text_field( wp_unslash( $_GET['orderby'] ) ); if ( in_array( $temp_orderby, $allowed_fields, true ) ) { $orderby = $temp_orderby; } } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading admin list state if ( isset( $_GET['order'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading admin list state $temp_order = strtoupper( sanitize_text_field( wp_unslash( $_GET['order'] ) ) ); if ( in_array( $temp_order, array( 'ASC', 'DESC' ), true ) ) { $order = $temp_order; } } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading admin list state if ( isset( $_GET['post_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading admin list state $temp_status = sanitize_text_field( wp_unslash( $_GET['post_status'] ) ); // Validate against allowed statuses $allowed_statuses = array( 'all', 'publish', 'draft', 'pending', 'private', 'future', 'trash' ); if ( in_array( $temp_status, $allowed_statuses, true ) ) { $post_status = $temp_status; } } return array( 'orderby' => $orderby, 'order' => $order, 'post_status' => $post_status, ); } // Apply to specific post types with dedicated filters add_filter( 'page_row_actions', 'ai_editor_add_order_to_edit_link', 10, 2 ); add_filter( 'post_row_actions', 'ai_editor_add_order_to_edit_link', 10, 2 ); // Apply to all post types to catch any CPTs add_action( 'admin_init', function() { // Get allowed post types from plugin settings $allowed_post_types = get_option( 'ai_editor_post_types', array( 'post', 'page' ) ); // Get all registered post types $post_types = get_post_types( array( 'show_ui' => true ), 'names' ); // Register our filter for each post type if supported by our plugin foreach ( $post_types as $post_type ) { // Skip post and page as they're already handled if ( 'post' === $post_type || 'page' === $post_type ) { continue; } // Only add filter if post type is in our allowed list if ( in_array( $post_type, $allowed_post_types, true ) ) { add_filter( $post_type . '_row_actions', 'ai_editor_add_order_to_edit_link', 10, 2 ); } } }); // As a fallback, also use the general post_row_actions filter for any missed CPTs add_filter( 'post_row_actions', function( $actions, $post ) { if ( 'post' !== $post->post_type && 'page' !== $post->post_type ) { return ai_editor_add_order_to_edit_link( $actions, $post ); } return $actions; }, 10, 2 );