AIOWPS Account Status
November 14, 2024 · AI Conversations
### Structure of `aiowps_account_status` Table
Here's a typical structure of the `aiowps_account_status` table:
| Column Name | Data Type | Description |
|——————|—————|——————————————————-|
| `id` | INT | Primary key (auto-incremented). |
| `username` | VARCHAR(255) | The WordPress username. |
| `failed_logins` | INT | The number of failed login attempts. |
| `account_lock` | TINYINT(1) | Whether the account is locked (1 = locked, 0 = not locked). |
| `lock_start` | DATETIME | The timestamp when the account was locked. |
| `unlock_key` | VARCHAR(255) | A key for unlocking the account (if applicable). |
| `last_login` | DATETIME | The timestamp of the last successful login. |
### Common Use Cases
1. **Account Lockout**:
– If a user exceeds the maximum number of failed login attempts, the plugin can lock their account temporarily or permanently depending on your settings.
2. **Tracking Failed Logins**:
– This table keeps a count of how many times a user has failed to log in, which can help prevent brute force attacks.
3. **Unlocking Accounts**:
– Admins can manually unlock user accounts if they were locked due to too many failed attempts.
### Example Queries
– **Reset Failed Login Attempts**:
UPDATE aiowps_account_status
SET failed_logins = 0
WHERE username = 'exampleuser';
– **Unlock a User Account**:
UPDATE aiowps_account_status
SET account_lock = 0, lock_start = NULL
WHERE username = 'exampleuser';
– **Check if an Account is Locked**:
SELECT *
FROM aiowps_account_status
WHERE username = 'exampleuser'
AND account_lock = 1;
These functionalities help improve your WordPress site's security by preventing unauthorized access and providing mechanisms for user account management.
UserWP plugin
### Objective
– When a user registers via the **UsersWP** plugin, their account will be created but set to "pending approval" status.
– Admin needs to approve the user manually, which will update the `aiowps_account_status` table to allow the user to log in.
### Implementation
#### Step 1: Add Pending Status to `aiowps_account_status`
1. **Hook into UsersWP Registration**
– Use the `uwp_after_user_register` action provided by UsersWP to add custom behavior after user registration.
2. **Insert or Update the `aiowps_account_status` Table**
Create a custom function in your WordPress theme's `functions.php` file or a custom plugin:
function custom_user_registration_approval($user_id) {
global $wpdb;
$user = get_userdata($user_id);
$username = $user->user_login;
// Check if the user already exists in aiowps_account_status
$table_name = $wpdb->prefix . 'aiowps_account_status';
$existing_user = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $table_name WHERE username = %s",
$username
));
if ($existing_user) {
// Update the account status to pending approval
$wpdb->update(
$table_name,
[
'account_lock' => 1, // Lock the account
'lock_start' => current_time('mysql')
],
['username' => $username]
);
} else {
// Insert a new entry for the user
$wpdb->insert(
$table_name,
[
'username' => $username,
'failed_logins' => 0,
'account_lock' => 1, // Lock the account
'lock_start' => current_time('mysql'),
'last_login' => NULL,
'unlock_key' => ''
]
);
}
}
add_action('uwp_after_user_register', 'custom_user_registration_approval', 10, 1);
#### Step 2: Create Admin Approval Interface
1. **Add a Menu in WordPress Admin Dashboard**
– You can create a custom admin page to list all users pending approval.
2. **Display Pending Users**
– Use the `get_results` method to fetch users from the `aiowps_account_status` table where `account_lock` is set to `1`.
function display_pending_users() {
global $wpdb;
$table_name = $wpdb->prefix . 'aiowps_account_status';
$pending_users = $wpdb->get_results("SELECT * FROM $table_name WHERE account_lock = 1");
echo '<h2>Pending User Approvals</h2>';
if ($pending_users) {
echo '<table><tr><th>Username</th><th>Actions</th></tr>';
foreach ($pending_users as $user) {
echo '<tr>';
echo '<td>' . esc_html($user->username) . '</td>';
echo '<td>';
echo '<a href="' . admin_url('admin.php?action=approve_user&username=' . urlencode($user->username)) . '">Approve</a>';
echo '</td>';
echo '</tr>';
}
echo '</table>';
} else {
echo '<p>No users pending approval.</p>';
}
}
add_action('admin_menu', function() {
add_menu_page('User Approval', 'User Approval', 'manage_options', 'user-approval', 'display_pending_users');
});
#### Step 3: Approve User Functionality
3. **Approve Users**
– Create a function to unlock user accounts by setting `account_lock` to `0`.
function approve_user() {
if (isset($_GET['action']) && $_GET['action'] === 'approve_user' && !empty($_GET['username'])) {
global $wpdb;
$username = sanitize_text_field($_GET['username']);
$table_name = $wpdb->prefix . 'aiowps_account_status';
// Unlock the account
$wpdb->update(
$table_name,
['account_lock' => 0, 'lock_start' => NULL],
['username' => $username]
);
wp_redirect(admin_url('admin.php?page=user-approval'));
exit;
}
}
add_action('admin_init', 'approve_user');
### Explanation
– **User Registration**: When a new user registers through UsersWP, they are automatically added to the `aiowps_account_status` table with `account_lock = 1`, meaning they cannot log in until approved.
– **Admin Interface**: Admins can view all pending users and approve them via a custom admin page.
– **Account Approval**: Once approved, the user's account is unlocked (`account_lock` is set to `0`), allowing them to log in.
This approach ensures your site remains secure by requiring admin approval before new users can access the system.
Here's how you can integrate **UsersWP** registration with **AIOWPS** using user metadata:
### Updated Implementation
#### Step 1: Set User to Pending Status Upon Registration
Add this code to your `functions.php` file or a custom plugin to set a newly registered user's account status to "locked" (pending admin approval):
function custom_user_registration_approval($user_id) {
// Set the 'aiowps_account_status' user meta to 'lock'
update_user_meta($user_id, 'aiowps_account_status', 'lock');
}
add_action('uwp_after_user_register', 'custom_user_registration_approval', 10, 1);
### Explanation
– When a new user registers via the **UsersWP** plugin, their account status is set to `lock` in the `usermeta` table.
– This will prevent the user from logging in until their account is approved.
#### Step 2: Create Admin Approval Interface
Create an admin page where you can view and approve users:
function display_pending_users() {
// Get all users with 'aiowps_account_status' set to 'lock'
$args = [
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID', 'user_login']
];
$pending_users = get_users($args);
echo '<h2>Pending User Approvals</h2>';
if (!empty($pending_users)) {
echo '<table><tr><th>Username</th><th>Actions</th></tr>';
foreach ($pending_users as $user) {
echo '<tr>';
echo '<td>' . esc_html($user->user_login) . '</td>';
echo '<td>';
echo '<a href="' . admin_url('admin.php?action=approve_user&user_id=' . $user->ID) . '">Approve</a>';
echo '</td>';
echo '</tr>';
}
echo '</table>';
} else {
echo '<p>No users pending approval.</p>';
}
}
add_action('admin_menu', function() {
add_menu_page('User Approval', 'User Approval', 'manage_options', 'user-approval', 'display_pending_users');
});
#### Step 3: Approve User Functionality
Add a function to unlock the user's account:
function approve_user() {
if (isset($_GET['action']) && $_GET['action'] === 'approve_user' && !empty($_GET['user_id'])) {
$user_id = intval($_GET['user_id']);
// Update 'aiowps_account_status' to allow login
update_user_meta($user_id, 'aiowps_account_status', 'unlock');
// Optional: Add a success notice
add_action('admin_notices', function() {
echo '<div class="updated"><p>User approved successfully!</p></div>';
});
wp_redirect(admin_url('admin.php?page=user-approval'));
exit;
}
}
add_action('admin_init', 'approve_user');
### Explanation
– **User Registration**: Users are marked as "locked" after registering.
– **Admin Interface**: Admins can see the list of users awaiting approval and unlock their accounts.
– **Unlock Users**: When approved, the `aiowps_account_status` meta key is updated to `unlock`, allowing users to log in.
This approach utilizes the existing user meta system, aligning with how `aiowps_account_status` is stored.
Here's how you can do it:
### Code to Check if UsersWP is Active
Add this snippet to your theme's `functions.php` file or a custom plugin:
function check_userswp_plugin_status() {
// Ensure the function is available
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
// Check if UsersWP plugin is active
if ( is_plugin_active( 'userswp/userswp.php' ) ) {
return true; // Plugin is active
} else {
return false; // Plugin is not active
}
}
// Example Usage
if ( check_userswp_plugin_status() ) {
// Your code for when UsersWP is active
error_log('UsersWP plugin is active.');
} else {
// Your code for when UsersWP is not active
error_log('UsersWP plugin is not active.');
}
### Explanation
1. **Include `plugin.php`**: The function `is_plugin_active()` is defined in `wp-admin/includes/plugin.php`, so it's necessary to include it if it's not already available.
2. **Check Plugin Status**: The `is_plugin_active()` function takes the path to the main plugin file relative to the `wp-content/plugins` directory (e.g., `userswp/userswp.php`).
### How to Get the Correct Plugin Path
– If you're unsure of the correct path for the UsersWP plugin, navigate to the `wp-content/plugins` directory and check the folder and main file name. Usually, it's `userswp/userswp.php`.
This code can help you conditionally execute specific logic only when the **UsersWP** plugin is active on your site.
### Updated Code with Plugin Check
function custom_user_registration_approval($user_id) {
// Check if the UsersWP plugin is active
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
if ( is_plugin_active( 'userswp/userswp.php' ) ) {
// Set the 'aiowps_account_status' user meta to 'lock' (pending approval)
update_user_meta($user_id, 'aiowps_account_status', 'lock');
}
}
add_action('uwp_after_user_register', 'custom_user_registration_approval', 10, 1);
### Explanation
1. **Check if UsersWP is Active**: Before setting the user meta, the code first checks if the **UsersWP** plugin is active using `is_plugin_active()`.
2. **Proceed with Registration Logic**: If **UsersWP** is active, the code proceeds to set the `aiowps_account_status` meta key to `lock` for the newly registered user, ensuring that their account is in a "pending approval" state.
This ensures the registration logic is only applied if **UsersWP** is active, preventing errors if the plugin is disabled.
// Get all users with 'aiowps_account_status' set to 'lock'
$args = [
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID', 'user_login']
];
$pending_users = get_users($args);
echo 'Pending User Approvals';
if (!empty($pending_users)) {
echo 'UsernameActions';
foreach ($pending_users as $user) {
echo '';
echo '' . esc_html($user->user_login) . '';
echo '';
echo 'Approve';
echo '';
echo '';
}
echo '';
} else {
echo 'No users pending approval.';
}
}
add_action('admin_menu', function() {
add_menu_page('User Approval', 'User Approval', 'manage_options', 'user-approval', 'display_pending_users');
});
add this userwp menu
Here's the updated code with the menu added under **UsersWP** if the plugin is active:
### Updated Code to Add Menu under UsersWP
function display_pending_users() {
// Get all users with 'aiowps_account_status' set to 'lock'
$args = [
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID', 'user_login']
];
$pending_users = get_users($args);
echo '<h2>Pending User Approvals</h2>';
if (!empty($pending_users)) {
echo '<table><tr><th>Username</th><th>Actions</th></tr>';
foreach ($pending_users as $user) {
echo '<tr>';
echo '<td>' . esc_html($user->user_login) . '</td>';
echo '<td>';
echo '<a href="' . admin_url('admin.php?action=approve_user&user_id=' . $user->ID) . '">Approve</a>';
echo '</td>';
echo '</tr>';
}
echo '</table>';
} else {
echo '<p>No users pending approval.</p>';
}
}
function add_userwp_menu_for_approval() {
// Check if the UsersWP plugin is active
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
// Add the menu under UsersWP if the plugin is active
if ( is_plugin_active( 'userswp/userswp.php' ) ) {
add_submenu_page(
'userswp', // Parent menu slug for UsersWP
'User Approval', // Page title
'User Approval', // Menu title
'manage_options', // Capability required to access the menu
'user-approval', // Menu slug
'display_pending_users' // Callback function to display the page
);
} else {
// If UsersWP is not active, add the menu under the main WordPress dashboard
add_menu_page(
'User Approval', // Page title
'User Approval', // Menu title
'manage_options', // Capability required to access the menu
'user-approval', // Menu slug
'display_pending_users' // Callback function to display the page
);
}
}
add_action('admin_menu', 'add_userwp_menu_for_approval');
### Explanation
1. **Check if UsersWP is Active**: The function `is_plugin_active()` checks if the **UsersWP** plugin is active.
2. **Menu Placement**:
– If **UsersWP** is active, the menu item will be added as a **sub-menu** under the **UsersWP** admin menu using `add_submenu_page()`.
– If **UsersWP** is not active, the menu item will be added directly to the WordPress dashboard using `add_menu_page()`.
3. **Display Pending Users**: The callback function `display_pending_users` remains the same and is used to display the list of users with `aiowps_account_status` set to `lock`.
### Final Notes
– **Menu Location**: With this approach, the **User Approval** menu will be nested under **UsersWP** if the plugin is active, providing a cleaner admin UI.
– **Permissions**: Ensure that users have the necessary `manage_options` capability to access this menu.
Here’s how to modify your `display_pending_users` function to use the `WP_List_Table` class:
### Updated Code to Use WP_List_Table
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
class Pending_User_Approval_List extends WP_List_Table {
// Constructor
public function __construct() {
parent::__construct( [
'singular' => 'user', // Singular name of the item
'plural' => 'users', // Plural name of the item
'ajax' => false, // Whether this table supports ajax
] );
}
// Prepare the items for the table
public function prepare_items() {
global $wpdb;
$per_page = 10; // Number of items per page
$current_page = $this->get_pagenum();
// Get the users with 'aiowps_account_status' set to 'lock'
$args = [
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID', 'user_login'],
'number' => $per_page,
'offset' => ( $current_page - 1 ) * $per_page
];
$users = get_users($args);
$total_users = count(get_users([
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID']
]));
// Prepare table columns
$columns = [
'username' => 'Username',
'actions' => 'Actions'
];
// Prepare the data (rows)
$data = [];
foreach ( $users as $user ) {
$data[] = [
'username' => $user->user_login,
'actions' => sprintf(
'<a href="%s">Approve</a>',
admin_url('admin.php?action=approve_user&user_id=' . $user->ID)
)
];
}
// Set the data for the table
$this->_column_headers = [ $columns, [], [] ];
$this->items = $data;
// Pagination
$this->set_pagination_args([
'total_items' => $total_users, // Total number of items
'per_page' => $per_page, // Number of items per page
'total_pages' => ceil($total_users / $per_page) // Total number of pages
]);
}
// Column output
public function column_username( $item ) {
return esc_html( $item['username'] );
}
public function column_actions( $item ) {
return $item['actions'];
}
}
// Display the list table
function display_pending_users() {
$pending_users_table = new Pending_User_Approval_List();
$pending_users_table->prepare_items();
?>
<div class="wrap">
<h2>Pending User Approvals</h2>
<form method="get">
<?php
$pending_users_table->search_box('search', 'search_id');
$pending_users_table->display();
?>
</form>
</div>
<?php
}
function add_userwp_menu_for_approval() {
// Check if the UsersWP plugin is active
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
// Add the menu under UsersWP if the plugin is active
if ( is_plugin_active( 'userswp/userswp.php' ) ) {
add_submenu_page(
'userswp', // Parent menu slug for UsersWP
'User Approval', // Page title
'User Approval', // Menu title
'manage_options', // Capability required to access the menu
'user-approval', // Menu slug
'display_pending_users' // Callback function to display the page
);
} else {
// If UsersWP is not active, add the menu under the main WordPress dashboard
add_menu_page(
'User Approval', // Page title
'User Approval', // Menu title
'manage_options', // Capability required to access the menu
'user-approval', // Menu slug
'display_pending_users' // Callback function to display the page
);
}
}
add_action('admin_menu', 'add_userwp_menu_for_approval');
### Explanation of Changes
1. **WP_List_Table Class**:
– We define a new class `Pending_User_Approval_List` that extends `WP_List_Table` to display users pending approval. This gives us access to WordPress’s built-in table structure.
– The `prepare_items()` method retrieves the pending users from the database and sets up the pagination.
– We define the columns `username` and `actions` to display the user’s username and the approve link, respectively.
2. **Display Table**:
– The `display_pending_users()` function creates an instance of the `Pending_User_Approval_List` table, prepares the items, and displays the table with pagination.
– The `search_box()` method adds a search box, though you can customize or remove it as needed.
3. **Pagination**:
– The `set_pagination_args()` method configures pagination for the table. It calculates the total pages and limits the number of users per page.
4. **Admin Menu**:
– The **User Approval** menu is added to the **UsersWP** section (if active) or the WordPress dashboard (if UsersWP is not active).
### Styling
This implementation uses the default WordPress styling for tables. The `WP_List_Table` class automatically applies the proper CSS classes, ensuring your table aligns with the rest of the WordPress admin interface.
### Final Notes
– This approach provides a more consistent user experience, following the WordPress admin design patterns.
– Pagination and sorting are built-in, so the table will be easier to navigate with large numbers of users.
### Steps
1. **Create a New File** for the Pending User Approval Page:
– Create a new file, say `pending-user-approval.php`, in your theme folder (for example, in `wp-content/themes/your-theme/`).
2. **Move the Code to the New File**:
– Copy the code related to the **Pending User Approval** functionality (the class definition and the `display_pending_users` function) into the new file.
3. **Include the New File in `functions.php`**:
– Use the `include` or `require` statement in your `functions.php` file to include the newly created PHP file.
### Step 1: Create the `pending-user-approval.php` File
Create the file `pending-user-approval.php` and place it in your theme's directory (`wp-content/themes/your-theme/`). Here's the content of the file:
<?php
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
class Pending_User_Approval_List extends WP_List_Table {
// Constructor
public function __construct() {
parent::__construct( [
'singular' => 'user', // Singular name of the item
'plural' => 'users', // Plural name of the item
'ajax' => false, // Whether this table supports ajax
] );
}
// Prepare the items for the table
public function prepare_items() {
global $wpdb;
$per_page = 10; // Number of items per page
$current_page = $this->get_pagenum();
// Get the users with 'aiowps_account_status' set to 'lock'
$args = [
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID', 'user_login'],
'number' => $per_page,
'offset' => ( $current_page - 1 ) * $per_page
];
$users = get_users($args);
$total_users = count(get_users([
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID']
]));
// Prepare table columns
$columns = [
'username' => 'Username',
'actions' => 'Actions'
];
// Prepare the data (rows)
$data = [];
foreach ( $users as $user ) {
$data[] = [
'username' => $user->user_login,
'actions' => sprintf(
'<a href="%s">Approve</a>',
admin_url('admin.php?action=approve_user&user_id=' . $user->ID)
)
];
}
// Set the data for the table
$this->_column_headers = [ $columns, [], [] ];
$this->items = $data;
// Pagination
$this->set_pagination_args([
'total_items' => $total_users, // Total number of items
'per_page' => $per_page, // Number of items per page
'total_pages' => ceil($total_users / $per_page) // Total number of pages
]);
}
// Column output
public function column_username( $item ) {
return esc_html( $item['username'] );
}
public function column_actions( $item ) {
return $item['actions'];
}
}
// Display the list table
function display_pending_users() {
$pending_users_table = new Pending_User_Approval_List();
$pending_users_table->prepare_items();
?>
<div class="wrap">
<h2>Pending User Approvals</h2>
<form method="get">
<?php
$pending_users_table->search_box('search', 'search_id');
$pending_users_table->display();
?>
</form>
</div>
<?php
}
function add_userwp_menu_for_approval() {
// Check if the UsersWP plugin is active
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
// Add the menu under UsersWP if the plugin is active
if ( is_plugin_active( 'userswp/userswp.php' ) ) {
add_submenu_page(
'userswp', // Parent menu slug for UsersWP
'User Approval', // Page title
'User Approval', // Menu title
'manage_options', // Capability required to access the menu
'user-approval', // Menu slug
'display_pending_users' // Callback function to display the page
);
} else {
// If UsersWP is not active, add the menu under the main WordPress dashboard
add_menu_page(
'User Approval', // Page title
'User Approval', // Menu title
'manage_options', // Capability required to access the menu
'user-approval', // Menu slug
'display_pending_users' // Callback function to display the page
);
}
}
### Step 2: Include the New File in `functions.php`
In your theme's `functions.php` file, include the `pending-user-approval.php` file:
// Include the Pending User Approval functionality
require_once get_template_directory() . '/pending-user-approval.php';
### Explanation
– **Separate File**: All the functionality for handling pending user approvals is now inside the `pending-user-approval.php` file. This file includes the class definition and the logic for displaying the list of users.
– **Include in `functions.php`**: The `require_once` statement in `functions.php` includes the `pending-user-approval.php` file, which means the functionality will still work but keeps the code modular and easy to manage.
### Final Notes
– Ensure the `pending-user-approval.php` file is in the correct location (in your theme's root directory or a subdirectory like `includes`).
– This approach allows you to keep your theme's `functions.php` file clean and organized, making your code easier to maintain and expand.
This typically happens when the file path is incorrect, or the file does not exist at the specified location.
### Steps to Fix the Issue:
1. **Check File Path**:
Ensure that the `userwp-activation-extension.php` file is located in the `resources` folder inside your theme directory. The error indicates that PHP is trying to access it at:
/home/aphasia/public_html/naa2023/web/app/themes/naa/resources/resources/userwp-activation-extension.php
This suggests that the `resources/` folder is being included twice. Verify that the file is located in:
/home/aphasia/public_html/naa2023/web/app/themes/naa/resources/userwp-activation-extension.php
If the file is indeed in the `resources/` folder, adjust the path accordingly.
2. **Adjust Include Path**:
In your `functions.php` file, you are probably using this code to include the file:
require_once get_template_directory() . '/resources/resources/userwp-activation-extension.php';
This is incorrect because it adds `resources/` twice to the path. You should update the `require_once` line in `functions.php` to:
require_once get_template_directory() . '/resources/userwp-activation-extension.php';
This way, it correctly points to the file inside the `resources` directory without duplicating the folder path.
3. **Verify File Existence**:
Make sure that the file `userwp-activation-extension.php` actually exists in the correct directory (`/home/aphasia/public_html/naa2023/web/app/themes/naa/resources/`). If it's missing, you will need to restore it or create it as required by your theme.
4. **Clear Caches**:
After making these changes, clear any caches if you're using a caching plugin or server-side caching to ensure that changes are reflected immediately.
### Example Adjustment in `functions.php`:
Before:
require_once get_template_directory() . '/resources/resources/userwp-activation-extension.php';
After:
require_once get_template_directory() . '/resources/userwp-activation-extension.php';
### Final Notes:
– Double-check that your file structure is correct and matches the path in the `require_once` statement.
– If the file doesn't exist in the specified location, you'll need to restore it or create the necessary file for your theme functionality.
### Solution
You need to implement the `get_columns()` method in your `Pending_User_Approval_List` class. This method should return an array with the column names and their labels. Here's how you can adjust your class to implement `get_columns()` and fix the error:
### Updated Code with `get_columns()`
<?php
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
class Pending_User_Approval_List extends WP_List_Table {
// Constructor
public function __construct() {
parent::__construct( [
'singular' => 'user', // Singular name of the item
'plural' => 'users', // Plural name of the item
'ajax' => false, // Whether this table supports ajax
] );
}
// Define the columns for the table
public function get_columns() {
// Return an array of columns with the column name as the key and label as the value
return [
'username' => 'Username',
'actions' => 'Actions',
];
}
// Prepare the items for the table
public function prepare_items() {
global $wpdb;
$per_page = 10; // Number of items per page
$current_page = $this->get_pagenum();
// Get the users with 'aiowps_account_status' set to 'lock'
$args = [
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID', 'user_login'],
'number' => $per_page,
'offset' => ( $current_page - 1 ) * $per_page
];
$users = get_users($args);
$total_users = count(get_users([
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID']
]));
// Prepare the data (rows)
$data = [];
foreach ( $users as $user ) {
$data[] = [
'username' => $user->user_login,
'actions' => sprintf(
'<a href="%s">Approve</a>',
admin_url('admin.php?action=approve_user&user_id=' . $user->ID)
)
];
}
// Set the data for the table
$this->items = $data;
// Pagination
$this->set_pagination_args([
'total_items' => $total_users, // Total number of items
'per_page' => $per_page, // Number of items per page
'total_pages' => ceil($total_users / $per_page) // Total number of pages
]);
}
// Column output
public function column_username( $item ) {
return esc_html( $item['username'] );
}
public function column_actions( $item ) {
return $item['actions'];
}
}
// Display the list table
function display_pending_users() {
$pending_users_table = new Pending_User_Approval_List();
$pending_users_table->prepare_items();
?>
<div class="wrap">
<h2>Pending User Approvals</h2>
<form method="get">
<?php
$pending_users_table->search_box('search', 'search_id');
$pending_users_table->display();
?>
</form>
</div>
<?php
}
function add_userwp_menu_for_approval() {
// Check if the UsersWP plugin is active
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
// Add the menu under UsersWP if the plugin is active
if ( is_plugin_active( 'userswp/userswp.php' ) ) {
add_submenu_page(
'userswp', // Parent menu slug for UsersWP
'User Approval', // Page title
'User Approval', // Menu title
'manage_options', // Capability required to access the menu
'user-approval', // Menu slug
'display_pending_users' // Callback function to display the page
);
} else {
// If UsersWP is not active, add the menu under the main WordPress dashboard
add_menu_page(
'User Approval', // Page title
'User Approval', // Menu title
'manage_options', // Capability required to access the menu
'user-approval', // Menu slug
'display_pending_users' // Callback function to display the page
);
}
}
### Key Changes:
1. **Implemented `get_columns()`**:
– This method returns an associative array where the keys are the column slugs and the values are the labels shown in the table header.
– In this case, we have two columns: `username` and `actions`.
2. **`prepare_items()`**:
– This method still gathers the users pending approval and prepares the data for display.
3. **`column_{column_name}` Methods**:
– These methods (`column_username()` and `column_actions()`) output the content for each column in the table.
### Final Notes:
– The `get_columns()` method is now properly defined to prevent the error from occurring.
– The table will display two columns: **Username** and **Actions** (with a link to approve the user).
– Make sure the path to the file where this class is defined is correct in your `functions.php`, as we discussed earlier.
With this implementation, you should no longer get the error about `get_columns()` being undefined.
### Potential Issues:
1. **No users with `aiowps_account_status` set to `'lock'`.**
2. **Incorrect table data preparation.**
3. **Issues with the pagination or data display logic.**
4. **Problems with the `column_{column_name}` methods.**
### Let's go through these potential issues and fix them.
### 1. **Check if Users Exist with `aiowps_account_status = 'lock'`**
First, ensure that there are users with the `aiowps_account_status` meta key set to `'lock'`. You can run the following query in your database to confirm that the users exist with this status:
SELECT * FROM wp_usermeta WHERE meta_key = 'aiowps_account_status' AND meta_value = 'lock';
If no results are returned, make sure users are actually being created with this status.
### 2. **Modify `prepare_items()` Method to Debug**
We need to add a check in the `prepare_items()` method to ensure users are being fetched properly.
Here's the updated `prepare_items()` method with debugging:
public function prepare_items() {
global $wpdb;
$per_page = 10; // Number of items per page
$current_page = $this->get_pagenum();
// Get the users with 'aiowps_account_status' set to 'lock'
$args = [
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID', 'user_login'],
'number' => $per_page,
'offset' => ( $current_page - 1 ) * $per_page
];
// Fetch users
$users = get_users($args);
// Debugging: Check if any users are fetched
if (empty($users)) {
error_log("No users found with aiowps_account_status = 'lock'");
}
// Get total users count for pagination
$total_users = count(get_users([
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID']
]));
// Prepare the data (rows)
$data = [];
foreach ($users as $user) {
$data[] = [
'username' => $user->user_login,
'actions' => sprintf(
'<a href="%s">Approve</a>',
admin_url('admin.php?action=approve_user&user_id=' . $user->ID)
)
];
}
// If no users, log a message
if (empty($data)) {
error_log("No pending users data to display.");
}
// Set the data for the table
$this->items = $data;
// Pagination
$this->set_pagination_args([
'total_items' => $total_users, // Total number of items
'per_page' => $per_page, // Number of items per page
'total_pages' => ceil($total_users / $per_page) // Total number of pages
]);
}
– This updated code adds some logging using `error_log()` to output debug messages to the PHP error log. Check your site's error logs to see if there are any issues with fetching users or if the users with the `'lock'` status are missing.
### 3. **Check `column_{column_name}` Methods**
Next, ensure that the `column_username` and `column_actions` methods are correctly outputting the data. Update the methods like this to make sure they are properly rendering the data:
public function column_username( $item ) {
return esc_html( $item['username'] );
}
public function column_actions( $item ) {
return $item['actions'];
}
### 4. **Test Table Output with Simple Data**
If the issue persists, test the table with hardcoded data to isolate the problem.
Modify the `prepare_items()` method like this:
public function prepare_items() {
$data = [
[
'username' => 'testuser',
'actions' => '<a href="#">Approve</a>',
],
[
'username' => 'anotheruser',
'actions' => '<a href="#">Approve</a>',
]
];
$this->items = $data;
}
This will allow you to test the table display without relying on the database. If the table shows with hardcoded data, the issue is likely with the database query.
### 5. **Ensure Table Display Works**
Finally, ensure that the table is properly rendered by calling `$pending_users_table->display()` inside the `display_pending_users()` function:
function display_pending_users() {
$pending_users_table = new Pending_User_Approval_List();
$pending_users_table->prepare_items(); // Prepare the data for display
?>
<div class="wrap">
<h2>Pending User Approvals</h2>
<form method="get">
<?php
// Display the search box and table
$pending_users_table->search_box('search', 'search_id');
$pending_users_table->display();
?>
</form>
</div>
<?php
}
### Conclusion
– Verify that the users with the `aiowps_account_status = 'lock'` exist in the database.
– Add debugging to check if the users are being fetched correctly.
– Test the table with hardcoded data to check if the issue is with the database query or the table display.
– Ensure the `column_username()` and `column_actions()` methods are correctly rendering the data.
After implementing these checks, you should be able to pinpoint the problem and resolve it.
### Step-by-Step Debugging and Solution:
1. **Check the `get_users` Query**:
If the number of items is being counted correctly but no actual records are showing, it could mean that the `get_users` query is fetching an empty result, or the data format is not being handled correctly in the table.
2. **Ensure Data is Being Set for `items`**:
In the `prepare_items` method, after fetching the users, check if the `$data` array is populated and being assigned to `$this->items`.
3. **Update the `prepare_items` Method**:
Let's add some debugging and refine the code to ensure everything is being handled properly.
### Updated `prepare_items` with Debugging:
public function prepare_items() {
global $wpdb;
$per_page = 10; // Number of items per page
$current_page = $this->get_pagenum();
// Get the users with 'aiowps_account_status' set to 'lock'
$args = [
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID', 'user_login'],
'number' => $per_page,
'offset' => ( $current_page - 1 ) * $per_page
];
// Fetch users
$users = get_users($args);
// Debugging: Check if any users are fetched
if (empty($users)) {
error_log("No users found with aiowps_account_status = 'lock'.");
} else {
error_log("Found users: " . count($users)); // Log how many users are fetched
}
// Get total users count for pagination
$total_users = count(get_users([
'meta_key' => 'aiowps_account_status',
'meta_value' => 'lock',
'fields' => ['ID']
]));
// Prepare the data (rows)
$data = [];
foreach ($users as $user) {
$data[] = [
'username' => $user->user_login,
'actions' => sprintf(
'<a href="%s">Approve</a>',
admin_url('admin.php?action=approve_user&user_id=' . $user->ID)
)
];
}
// Debugging: Check if data is populated
if (empty($data)) {
error_log("No pending users data to display.");
} else {
error_log("Pending users data: " . print_r($data, true)); // Log data array for debugging
}
// Set the data for the table
$this->items = $data;
// Pagination
$this->set_pagination_args([
'total_items' => $total_users, // Total number of items
'per_page' => $per_page, // Number of items per page
'total_pages' => ceil($total_users / $per_page) // Total number of pages
]);
}
### Key Changes and Debugging:
1. **Logging User Count**:
We added a log to check how many users were fetched. You can check the PHP error log (`error_log`) to see if any users are returned with the query. If no users are returned, the issue is likely with the database query or the user status.
2. **Logging Data Array**:
After populating the `$data` array, we log its contents. This will help you verify if the data is being populated correctly for display in the table.
### Check Your PHP Error Log
1. Enable error logging in `wp-config.php` (if it's not already enabled):
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
2. Check the error log at `/wp-content/debug.log` for the debug messages. This will help you identify if the users are being fetched and if the `$data` array is populated correctly.
### Further Improvements
1. **Pagination Issue**:
– Make sure the pagination works as expected by verifying the value of `$total_users` and the resulting number of pages.
– If the number of pages is correct, but no data is displayed, the issue might be in how `$this->items` is populated or displayed.
2. **Ensure Correct Column Methods**:
Double-check that the `column_username` and `column_actions` methods are correctly implemented to render the columns:
public function column_username( $item ) {
return esc_html( $item['username'] );
}
public function column_actions( $item ) {
return $item['actions'];
}
3. **Manual Data Test**:
If the debug logs show that users are still not being fetched, test with hardcoded data in `prepare_items`:
public function prepare_items() {
$data = [
[
'username' => 'testuser',
'actions' => '<a href="#">Approve</a>',
],
[
'username' => 'anotheruser',
'actions' => '<a href="#">Approve</a>',
]
];
$this->items = $data; // Set the items
}
This will ensure that the table structure itself is functioning properly.
### Conclusion
– **Check the error log** to verify whether users are being fetched and whether the `$data` array is populated.
– **Verify that the query works** by checking if users with `aiowps_account_status = 'lock'` exist in the database.
– **Test with hardcoded data** if necessary to isolate the issue.