Implementing automated compliance reporting for custom internal server status logs ledgers using custom PHP-Spreadsheet exports
// Add this to your plugin's main file or an included file
add_action('admin_menu', 'add_server_status_report_menu');
function add_server_status_report_menu() {
add_management_page(
'Server Status Report',
'Server Status Report',
'manage_options', // Capability required to access
'server-status-report',
'render_server_status_report_page'
);
}
function render_server_status_report_page() {
?>
Server Status Compliance Report
Click the button below to generate the latest server status compliance report.
$_POST['start_date'], 'server_name' => $_POST['server_name']]
if (generate_server_status_report($outputFilePath, $filters)) {
echo 'Report generated successfully: ' . esc_html($fileName) . '
';
} else {
echo 'Failed to generate report.
';
}
}
?>
Example: WP-Cron Job for Automated Reporting
To automate this, we can use WP-Cron. First, schedule a custom cron event. Then, create a function that runs on that event.
// Add to your plugin's main file or an included file
// 1. Schedule the event on plugin activation
register_activation_hook(__FILE__, 'schedule_server_status_report_cron');
function schedule_server_status_report_cron() {
if (!wp_next_scheduled('daily_server_status_report')) {
// Schedule to run daily at 2 AM
wp_schedule_event(time(), 'daily', 'daily_server_status_report');
}
}
// 2. Hook the function to the scheduled event
add_action('daily_server_status_report', 'run_automated_server_status_report');
function run_automated_server_status_report() {
$uploadDir = wp_upload_dir();
$reportDir = trailingslashit($uploadDir['basedir']) . 'server-reports/';
if (!file_exists($reportDir)) {
wp_mkdir_p($reportDir);
}
$fileName = 'server_status_report_' . date('Ymd') . '.xlsx'; // Daily report, no time needed
$outputFilePath = $reportDir . $fileName;
// Define filters for the automated report (e.g., last 24 hours)
$filters = [
'start_date' => date('Y-m-d', strtotime('-1 day')),
'end_date' => date('Y-m-d'),
];
if (generate_server_status_report($outputFilePath, $filters)) {
// Optionally send an email notification on success
// wp_mail('[email protected]', 'Server Report Generated', 'The daily server status report was generated successfully.');
} else {
// Optionally send an email notification on failure
// wp_mail('[email protected]', 'Server Report Generation FAILED', 'The daily server status report failed to generate.');
}
}
// 3. Unschedule the event on plugin deactivation
register_deactivation_hook(__FILE__, 'unschedule_server_status_report_cron');
function unschedule_server_status_report_cron() {
$timestamp = wp_next_scheduled('daily_server_status_report');
if ($timestamp) {
wp_unschedule_event($timestamp, 'daily_server_status_report');
}
}
// Ensure the generate_server_status_report function is defined or included before this.
// Also ensure the Composer autoloader is included.
Advanced Considerations and Best Practices
- Error Handling: Implement robust error handling for database queries and file operations. Log errors to the WordPress debug log or a custom error log.
- Security: Sanitize all user inputs if using an admin page. Use nonces to prevent CSRF attacks. Ensure the generated reports are stored in a secure location, and consider access controls if they contain sensitive information.
- Performance: For very large log datasets, consider fetching data in batches or optimizing the SQL query. PHP-Spreadsheet can consume significant memory for large files; monitor resource usage.
- File Management: Implement a strategy for managing old report files to prevent disk space exhaustion (e.g., delete reports older than X days).
- Configuration: Allow users to configure report parameters (date ranges, servers, output format) through the WordPress admin interface.
- Alternative Formats: PHP-Spreadsheet supports various formats beyond XLSX, including CSV, PDF, HTML, and ODS. Adapt the writer class accordingly if other formats are required.
By integrating PHP-Spreadsheet into your WordPress development workflow, you can create powerful, automated reporting solutions that significantly reduce manual effort and improve compliance adherence for custom internal systems.
/**
* Generates a compliance report from server status logs.
*
* @param string $outputFilePath The full path where the XLSX file will be saved.
* @param array $filters Optional array of filters (e.g., 'start_date', 'end_date', 'server_name').
* @return bool True on success, false on failure.
*/
function generate_server_status_report(string $outputFilePath, array $filters = []): bool
{
global $wpdb;
$tableName = $wpdb->prefix . 'server_status_logs';
// 1. Fetch Log Data with Filters
$query = "SELECT timestamp, server_name, status_code, response_time_ms, error_message FROM {$tableName}";
$whereClauses = [];
$queryArgs = [];
if (!empty($filters['start_date'])) {
$whereClauses[] = "timestamp >= %s";
$queryArgs[] = sanitize_text_field($filters['start_date']) . ' 00:00:00';
}
if (!empty($filters['end_date'])) {
$whereClauses[] = "timestamp <= %s";
$queryArgs[] = sanitize_text_field($filters['end_date']) . ' 23:59:59';
}
if (!empty($filters['server_name'])) {
$whereClauses[] = "server_name = %s";
$queryArgs[] = sanitize_text_field($filters['server_name']);
}
if (!empty($whereClauses)) {
$query .= " WHERE " . implode(' AND ', $whereClauses);
}
$query .= " ORDER BY timestamp ASC";
$logs = $wpdb->get_results($wpdb->prepare($query, $queryArgs), ARRAY_A);
if ($logs === null) {
error_log("Failed to fetch server status logs: " . $wpdb->last_error);
return false;
}
// 2. Initialize PHP-Spreadsheet
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 3. Set Headers
$headers = ['Timestamp', 'Server Name', 'Status Code', 'Response Time (ms)', 'Error Message'];
$sheet->fromArray([$headers], NULL, 'A1');
// Apply header styling (optional)
$headerStyle = [
'font' => ['bold' => true],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['argb' => 'FFD3D3D3']],
];
$sheet->getStyle('A1:' . $sheet->getCellByColumnAndRow(count($headers), 1)->getColumn() . '1')->applyFromArray($headerStyle);
// 4. Populate Data Rows
$rowNum = 2; // Start from the second row
foreach ($logs as $log) {
$sheet->setCellValue('A' . $rowNum, $log['timestamp']);
$sheet->setCellValue('B' . $rowNum, $log['server_name']);
$sheet->setCellValue('C' . $rowNum, $log['status_code']);
$sheet->setCellValue('D' . $rowNum, $log['response_time_ms'] ?? ''); // Handle null values
$sheet->setCellValue('E' . $rowNum, $log['error_message'] ?? ''); // Handle null values
$rowNum++;
}
// 5. Auto-size Columns for better readability
foreach (range('A', $sheet->getHighestDataColumn()) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
// 6. Create the Writer and Save the File
$writer = new Xlsx($spreadsheet);
try {
$writer->save($outputFilePath);
return true;
} catch (\Exception $e) {
error_log("Failed to save spreadsheet report to {$outputFilePath}: " . $e->getMessage());
return false;
}
}
Integrating with WordPress
To make this report generation accessible, we can hook it into WordPress's functionality. Two common approaches are:
- Admin Page Button: Create a custom admin page where users can click a button to generate and download the report.
- WP-Cron Job: Schedule the report generation to run automatically at regular intervals (e.g., daily, weekly).
Example: Admin Page Button for Manual Generation
This example shows how to add a simple admin page with a button to trigger the report generation. The generated file will be saved to the WordPress uploads directory.
// Add this to your plugin's main file or an included file
add_action('admin_menu', 'add_server_status_report_menu');
function add_server_status_report_menu() {
add_management_page(
'Server Status Report',
'Server Status Report',
'manage_options', // Capability required to access
'server-status-report',
'render_server_status_report_page'
);
}
function render_server_status_report_page() {
?>
Server Status Compliance Report
Click the button below to generate the latest server status compliance report.
$_POST['start_date'], 'server_name' => $_POST['server_name']]
if (generate_server_status_report($outputFilePath, $filters)) {
echo 'Report generated successfully: ' . esc_html($fileName) . '
';
} else {
echo 'Failed to generate report.
';
}
}
?>
Example: WP-Cron Job for Automated Reporting
To automate this, we can use WP-Cron. First, schedule a custom cron event. Then, create a function that runs on that event.
// Add to your plugin's main file or an included file
// 1. Schedule the event on plugin activation
register_activation_hook(__FILE__, 'schedule_server_status_report_cron');
function schedule_server_status_report_cron() {
if (!wp_next_scheduled('daily_server_status_report')) {
// Schedule to run daily at 2 AM
wp_schedule_event(time(), 'daily', 'daily_server_status_report');
}
}
// 2. Hook the function to the scheduled event
add_action('daily_server_status_report', 'run_automated_server_status_report');
function run_automated_server_status_report() {
$uploadDir = wp_upload_dir();
$reportDir = trailingslashit($uploadDir['basedir']) . 'server-reports/';
if (!file_exists($reportDir)) {
wp_mkdir_p($reportDir);
}
$fileName = 'server_status_report_' . date('Ymd') . '.xlsx'; // Daily report, no time needed
$outputFilePath = $reportDir . $fileName;
// Define filters for the automated report (e.g., last 24 hours)
$filters = [
'start_date' => date('Y-m-d', strtotime('-1 day')),
'end_date' => date('Y-m-d'),
];
if (generate_server_status_report($outputFilePath, $filters)) {
// Optionally send an email notification on success
// wp_mail('[email protected]', 'Server Report Generated', 'The daily server status report was generated successfully.');
} else {
// Optionally send an email notification on failure
// wp_mail('[email protected]', 'Server Report Generation FAILED', 'The daily server status report failed to generate.');
}
}
// 3. Unschedule the event on plugin deactivation
register_deactivation_hook(__FILE__, 'unschedule_server_status_report_cron');
function unschedule_server_status_report_cron() {
$timestamp = wp_next_scheduled('daily_server_status_report');
if ($timestamp) {
wp_unschedule_event($timestamp, 'daily_server_status_report');
}
}
// Ensure the generate_server_status_report function is defined or included before this.
// Also ensure the Composer autoloader is included.
Advanced Considerations and Best Practices
- Error Handling: Implement robust error handling for database queries and file operations. Log errors to the WordPress debug log or a custom error log.
- Security: Sanitize all user inputs if using an admin page. Use nonces to prevent CSRF attacks. Ensure the generated reports are stored in a secure location, and consider access controls if they contain sensitive information.
- Performance: For very large log datasets, consider fetching data in batches or optimizing the SQL query. PHP-Spreadsheet can consume significant memory for large files; monitor resource usage.
- File Management: Implement a strategy for managing old report files to prevent disk space exhaustion (e.g., delete reports older than X days).
- Configuration: Allow users to configure report parameters (date ranges, servers, output format) through the WordPress admin interface.
- Alternative Formats: PHP-Spreadsheet supports various formats beyond XLSX, including CSV, PDF, HTML, and ODS. Adapt the writer class accordingly if other formats are required.
By integrating PHP-Spreadsheet into your WordPress development workflow, you can create powerful, automated reporting solutions that significantly reduce manual effort and improve compliance adherence for custom internal systems.
-- Example table structure
CREATE TABLE wp_server_status_logs (
log_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME NOT NULL,
server_name VARCHAR(255) NOT NULL,
status_code INT NOT NULL,
response_time_ms INT NULL,
error_message TEXT NULL
);
Implementing the Report Generation Logic
We'll create a function that queries the log data, processes it, and then uses PHP-Spreadsheet to generate an XLSX file. This function could be triggered by a WordPress cron job or a custom admin page button.
Here's a PHP function that accomplishes this:
/**
* Generates a compliance report from server status logs.
*
* @param string $outputFilePath The full path where the XLSX file will be saved.
* @param array $filters Optional array of filters (e.g., 'start_date', 'end_date', 'server_name').
* @return bool True on success, false on failure.
*/
function generate_server_status_report(string $outputFilePath, array $filters = []): bool
{
global $wpdb;
$tableName = $wpdb->prefix . 'server_status_logs';
// 1. Fetch Log Data with Filters
$query = "SELECT timestamp, server_name, status_code, response_time_ms, error_message FROM {$tableName}";
$whereClauses = [];
$queryArgs = [];
if (!empty($filters['start_date'])) {
$whereClauses[] = "timestamp >= %s";
$queryArgs[] = sanitize_text_field($filters['start_date']) . ' 00:00:00';
}
if (!empty($filters['end_date'])) {
$whereClauses[] = "timestamp <= %s";
$queryArgs[] = sanitize_text_field($filters['end_date']) . ' 23:59:59';
}
if (!empty($filters['server_name'])) {
$whereClauses[] = "server_name = %s";
$queryArgs[] = sanitize_text_field($filters['server_name']);
}
if (!empty($whereClauses)) {
$query .= " WHERE " . implode(' AND ', $whereClauses);
}
$query .= " ORDER BY timestamp ASC";
$logs = $wpdb->get_results($wpdb->prepare($query, $queryArgs), ARRAY_A);
if ($logs === null) {
error_log("Failed to fetch server status logs: " . $wpdb->last_error);
return false;
}
// 2. Initialize PHP-Spreadsheet
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 3. Set Headers
$headers = ['Timestamp', 'Server Name', 'Status Code', 'Response Time (ms)', 'Error Message'];
$sheet->fromArray([$headers], NULL, 'A1');
// Apply header styling (optional)
$headerStyle = [
'font' => ['bold' => true],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['argb' => 'FFD3D3D3']],
];
$sheet->getStyle('A1:' . $sheet->getCellByColumnAndRow(count($headers), 1)->getColumn() . '1')->applyFromArray($headerStyle);
// 4. Populate Data Rows
$rowNum = 2; // Start from the second row
foreach ($logs as $log) {
$sheet->setCellValue('A' . $rowNum, $log['timestamp']);
$sheet->setCellValue('B' . $rowNum, $log['server_name']);
$sheet->setCellValue('C' . $rowNum, $log['status_code']);
$sheet->setCellValue('D' . $rowNum, $log['response_time_ms'] ?? ''); // Handle null values
$sheet->setCellValue('E' . $rowNum, $log['error_message'] ?? ''); // Handle null values
$rowNum++;
}
// 5. Auto-size Columns for better readability
foreach (range('A', $sheet->getHighestDataColumn()) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
// 6. Create the Writer and Save the File
$writer = new Xlsx($spreadsheet);
try {
$writer->save($outputFilePath);
return true;
} catch (\Exception $e) {
error_log("Failed to save spreadsheet report to {$outputFilePath}: " . $e->getMessage());
return false;
}
}
Integrating with WordPress
To make this report generation accessible, we can hook it into WordPress's functionality. Two common approaches are:
- Admin Page Button: Create a custom admin page where users can click a button to generate and download the report.
- WP-Cron Job: Schedule the report generation to run automatically at regular intervals (e.g., daily, weekly).
Example: Admin Page Button for Manual Generation
This example shows how to add a simple admin page with a button to trigger the report generation. The generated file will be saved to the WordPress uploads directory.
// Add this to your plugin's main file or an included file
add_action('admin_menu', 'add_server_status_report_menu');
function add_server_status_report_menu() {
add_management_page(
'Server Status Report',
'Server Status Report',
'manage_options', // Capability required to access
'server-status-report',
'render_server_status_report_page'
);
}
function render_server_status_report_page() {
?>
Server Status Compliance Report
Click the button below to generate the latest server status compliance report.
$_POST['start_date'], 'server_name' => $_POST['server_name']]
if (generate_server_status_report($outputFilePath, $filters)) {
echo 'Report generated successfully: ' . esc_html($fileName) . '
';
} else {
echo 'Failed to generate report.
';
}
}
?>
Example: WP-Cron Job for Automated Reporting
To automate this, we can use WP-Cron. First, schedule a custom cron event. Then, create a function that runs on that event.
// Add to your plugin's main file or an included file
// 1. Schedule the event on plugin activation
register_activation_hook(__FILE__, 'schedule_server_status_report_cron');
function schedule_server_status_report_cron() {
if (!wp_next_scheduled('daily_server_status_report')) {
// Schedule to run daily at 2 AM
wp_schedule_event(time(), 'daily', 'daily_server_status_report');
}
}
// 2. Hook the function to the scheduled event
add_action('daily_server_status_report', 'run_automated_server_status_report');
function run_automated_server_status_report() {
$uploadDir = wp_upload_dir();
$reportDir = trailingslashit($uploadDir['basedir']) . 'server-reports/';
if (!file_exists($reportDir)) {
wp_mkdir_p($reportDir);
}
$fileName = 'server_status_report_' . date('Ymd') . '.xlsx'; // Daily report, no time needed
$outputFilePath = $reportDir . $fileName;
// Define filters for the automated report (e.g., last 24 hours)
$filters = [
'start_date' => date('Y-m-d', strtotime('-1 day')),
'end_date' => date('Y-m-d'),
];
if (generate_server_status_report($outputFilePath, $filters)) {
// Optionally send an email notification on success
// wp_mail('[email protected]', 'Server Report Generated', 'The daily server status report was generated successfully.');
} else {
// Optionally send an email notification on failure
// wp_mail('[email protected]', 'Server Report Generation FAILED', 'The daily server status report failed to generate.');
}
}
// 3. Unschedule the event on plugin deactivation
register_deactivation_hook(__FILE__, 'unschedule_server_status_report_cron');
function unschedule_server_status_report_cron() {
$timestamp = wp_next_scheduled('daily_server_status_report');
if ($timestamp) {
wp_unschedule_event($timestamp, 'daily_server_status_report');
}
}
// Ensure the generate_server_status_report function is defined or included before this.
// Also ensure the Composer autoloader is included.
Advanced Considerations and Best Practices
- Error Handling: Implement robust error handling for database queries and file operations. Log errors to the WordPress debug log or a custom error log.
- Security: Sanitize all user inputs if using an admin page. Use nonces to prevent CSRF attacks. Ensure the generated reports are stored in a secure location, and consider access controls if they contain sensitive information.
- Performance: For very large log datasets, consider fetching data in batches or optimizing the SQL query. PHP-Spreadsheet can consume significant memory for large files; monitor resource usage.
- File Management: Implement a strategy for managing old report files to prevent disk space exhaustion (e.g., delete reports older than X days).
- Configuration: Allow users to configure report parameters (date ranges, servers, output format) through the WordPress admin interface.
- Alternative Formats: PHP-Spreadsheet supports various formats beyond XLSX, including CSV, PDF, HTML, and ODS. Adapt the writer class accordingly if other formats are required.
By integrating PHP-Spreadsheet into your WordPress development workflow, you can create powerful, automated reporting solutions that significantly reduce manual effort and improve compliance adherence for custom internal systems.
// In your plugin's main file (e.g., my-custom-plugin.php) require_once __DIR__ . '/vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // ... rest of your plugin code
Designing the Custom Log Structure
For this example, let's assume your custom server status logs are stored in a custom database table, perhaps named wp_server_status_logs. Each entry might contain fields like log_id, timestamp, server_name, status_code, response_time_ms, and error_message.
A typical log entry might look like this in the database:
-- Example table structure
CREATE TABLE wp_server_status_logs (
log_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME NOT NULL,
server_name VARCHAR(255) NOT NULL,
status_code INT NOT NULL,
response_time_ms INT NULL,
error_message TEXT NULL
);
Implementing the Report Generation Logic
We'll create a function that queries the log data, processes it, and then uses PHP-Spreadsheet to generate an XLSX file. This function could be triggered by a WordPress cron job or a custom admin page button.
Here's a PHP function that accomplishes this:
/**
* Generates a compliance report from server status logs.
*
* @param string $outputFilePath The full path where the XLSX file will be saved.
* @param array $filters Optional array of filters (e.g., 'start_date', 'end_date', 'server_name').
* @return bool True on success, false on failure.
*/
function generate_server_status_report(string $outputFilePath, array $filters = []): bool
{
global $wpdb;
$tableName = $wpdb->prefix . 'server_status_logs';
// 1. Fetch Log Data with Filters
$query = "SELECT timestamp, server_name, status_code, response_time_ms, error_message FROM {$tableName}";
$whereClauses = [];
$queryArgs = [];
if (!empty($filters['start_date'])) {
$whereClauses[] = "timestamp >= %s";
$queryArgs[] = sanitize_text_field($filters['start_date']) . ' 00:00:00';
}
if (!empty($filters['end_date'])) {
$whereClauses[] = "timestamp <= %s";
$queryArgs[] = sanitize_text_field($filters['end_date']) . ' 23:59:59';
}
if (!empty($filters['server_name'])) {
$whereClauses[] = "server_name = %s";
$queryArgs[] = sanitize_text_field($filters['server_name']);
}
if (!empty($whereClauses)) {
$query .= " WHERE " . implode(' AND ', $whereClauses);
}
$query .= " ORDER BY timestamp ASC";
$logs = $wpdb->get_results($wpdb->prepare($query, $queryArgs), ARRAY_A);
if ($logs === null) {
error_log("Failed to fetch server status logs: " . $wpdb->last_error);
return false;
}
// 2. Initialize PHP-Spreadsheet
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 3. Set Headers
$headers = ['Timestamp', 'Server Name', 'Status Code', 'Response Time (ms)', 'Error Message'];
$sheet->fromArray([$headers], NULL, 'A1');
// Apply header styling (optional)
$headerStyle = [
'font' => ['bold' => true],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['argb' => 'FFD3D3D3']],
];
$sheet->getStyle('A1:' . $sheet->getCellByColumnAndRow(count($headers), 1)->getColumn() . '1')->applyFromArray($headerStyle);
// 4. Populate Data Rows
$rowNum = 2; // Start from the second row
foreach ($logs as $log) {
$sheet->setCellValue('A' . $rowNum, $log['timestamp']);
$sheet->setCellValue('B' . $rowNum, $log['server_name']);
$sheet->setCellValue('C' . $rowNum, $log['status_code']);
$sheet->setCellValue('D' . $rowNum, $log['response_time_ms'] ?? ''); // Handle null values
$sheet->setCellValue('E' . $rowNum, $log['error_message'] ?? ''); // Handle null values
$rowNum++;
}
// 5. Auto-size Columns for better readability
foreach (range('A', $sheet->getHighestDataColumn()) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
// 6. Create the Writer and Save the File
$writer = new Xlsx($spreadsheet);
try {
$writer->save($outputFilePath);
return true;
} catch (\Exception $e) {
error_log("Failed to save spreadsheet report to {$outputFilePath}: " . $e->getMessage());
return false;
}
}
Integrating with WordPress
To make this report generation accessible, we can hook it into WordPress's functionality. Two common approaches are:
- Admin Page Button: Create a custom admin page where users can click a button to generate and download the report.
- WP-Cron Job: Schedule the report generation to run automatically at regular intervals (e.g., daily, weekly).
Example: Admin Page Button for Manual Generation
This example shows how to add a simple admin page with a button to trigger the report generation. The generated file will be saved to the WordPress uploads directory.
// Add this to your plugin's main file or an included file
add_action('admin_menu', 'add_server_status_report_menu');
function add_server_status_report_menu() {
add_management_page(
'Server Status Report',
'Server Status Report',
'manage_options', // Capability required to access
'server-status-report',
'render_server_status_report_page'
);
}
function render_server_status_report_page() {
?>
Server Status Compliance Report
Click the button below to generate the latest server status compliance report.
$_POST['start_date'], 'server_name' => $_POST['server_name']]
if (generate_server_status_report($outputFilePath, $filters)) {
echo 'Report generated successfully: ' . esc_html($fileName) . '
';
} else {
echo 'Failed to generate report.
';
}
}
?>
Example: WP-Cron Job for Automated Reporting
To automate this, we can use WP-Cron. First, schedule a custom cron event. Then, create a function that runs on that event.
// Add to your plugin's main file or an included file
// 1. Schedule the event on plugin activation
register_activation_hook(__FILE__, 'schedule_server_status_report_cron');
function schedule_server_status_report_cron() {
if (!wp_next_scheduled('daily_server_status_report')) {
// Schedule to run daily at 2 AM
wp_schedule_event(time(), 'daily', 'daily_server_status_report');
}
}
// 2. Hook the function to the scheduled event
add_action('daily_server_status_report', 'run_automated_server_status_report');
function run_automated_server_status_report() {
$uploadDir = wp_upload_dir();
$reportDir = trailingslashit($uploadDir['basedir']) . 'server-reports/';
if (!file_exists($reportDir)) {
wp_mkdir_p($reportDir);
}
$fileName = 'server_status_report_' . date('Ymd') . '.xlsx'; // Daily report, no time needed
$outputFilePath = $reportDir . $fileName;
// Define filters for the automated report (e.g., last 24 hours)
$filters = [
'start_date' => date('Y-m-d', strtotime('-1 day')),
'end_date' => date('Y-m-d'),
];
if (generate_server_status_report($outputFilePath, $filters)) {
// Optionally send an email notification on success
// wp_mail('[email protected]', 'Server Report Generated', 'The daily server status report was generated successfully.');
} else {
// Optionally send an email notification on failure
// wp_mail('[email protected]', 'Server Report Generation FAILED', 'The daily server status report failed to generate.');
}
}
// 3. Unschedule the event on plugin deactivation
register_deactivation_hook(__FILE__, 'unschedule_server_status_report_cron');
function unschedule_server_status_report_cron() {
$timestamp = wp_next_scheduled('daily_server_status_report');
if ($timestamp) {
wp_unschedule_event($timestamp, 'daily_server_status_report');
}
}
// Ensure the generate_server_status_report function is defined or included before this.
// Also ensure the Composer autoloader is included.
Advanced Considerations and Best Practices
- Error Handling: Implement robust error handling for database queries and file operations. Log errors to the WordPress debug log or a custom error log.
- Security: Sanitize all user inputs if using an admin page. Use nonces to prevent CSRF attacks. Ensure the generated reports are stored in a secure location, and consider access controls if they contain sensitive information.
- Performance: For very large log datasets, consider fetching data in batches or optimizing the SQL query. PHP-Spreadsheet can consume significant memory for large files; monitor resource usage.
- File Management: Implement a strategy for managing old report files to prevent disk space exhaustion (e.g., delete reports older than X days).
- Configuration: Allow users to configure report parameters (date ranges, servers, output format) through the WordPress admin interface.
- Alternative Formats: PHP-Spreadsheet supports various formats beyond XLSX, including CSV, PDF, HTML, and ODS. Adapt the writer class accordingly if other formats are required.
By integrating PHP-Spreadsheet into your WordPress development workflow, you can create powerful, automated reporting solutions that significantly reduce manual effort and improve compliance adherence for custom internal systems.
composer require phpoffice/phpspreadsheet
This command will download the library and its dependencies into a vendor directory and update your composer.json and composer.lock files. You'll then need to include the Composer autoloader in your WordPress plugin or theme's main file.
// In your plugin's main file (e.g., my-custom-plugin.php) require_once __DIR__ . '/vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // ... rest of your plugin code
Designing the Custom Log Structure
For this example, let's assume your custom server status logs are stored in a custom database table, perhaps named wp_server_status_logs. Each entry might contain fields like log_id, timestamp, server_name, status_code, response_time_ms, and error_message.
A typical log entry might look like this in the database:
-- Example table structure
CREATE TABLE wp_server_status_logs (
log_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME NOT NULL,
server_name VARCHAR(255) NOT NULL,
status_code INT NOT NULL,
response_time_ms INT NULL,
error_message TEXT NULL
);
Implementing the Report Generation Logic
We'll create a function that queries the log data, processes it, and then uses PHP-Spreadsheet to generate an XLSX file. This function could be triggered by a WordPress cron job or a custom admin page button.
Here's a PHP function that accomplishes this:
/**
* Generates a compliance report from server status logs.
*
* @param string $outputFilePath The full path where the XLSX file will be saved.
* @param array $filters Optional array of filters (e.g., 'start_date', 'end_date', 'server_name').
* @return bool True on success, false on failure.
*/
function generate_server_status_report(string $outputFilePath, array $filters = []): bool
{
global $wpdb;
$tableName = $wpdb->prefix . 'server_status_logs';
// 1. Fetch Log Data with Filters
$query = "SELECT timestamp, server_name, status_code, response_time_ms, error_message FROM {$tableName}";
$whereClauses = [];
$queryArgs = [];
if (!empty($filters['start_date'])) {
$whereClauses[] = "timestamp >= %s";
$queryArgs[] = sanitize_text_field($filters['start_date']) . ' 00:00:00';
}
if (!empty($filters['end_date'])) {
$whereClauses[] = "timestamp <= %s";
$queryArgs[] = sanitize_text_field($filters['end_date']) . ' 23:59:59';
}
if (!empty($filters['server_name'])) {
$whereClauses[] = "server_name = %s";
$queryArgs[] = sanitize_text_field($filters['server_name']);
}
if (!empty($whereClauses)) {
$query .= " WHERE " . implode(' AND ', $whereClauses);
}
$query .= " ORDER BY timestamp ASC";
$logs = $wpdb->get_results($wpdb->prepare($query, $queryArgs), ARRAY_A);
if ($logs === null) {
error_log("Failed to fetch server status logs: " . $wpdb->last_error);
return false;
}
// 2. Initialize PHP-Spreadsheet
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 3. Set Headers
$headers = ['Timestamp', 'Server Name', 'Status Code', 'Response Time (ms)', 'Error Message'];
$sheet->fromArray([$headers], NULL, 'A1');
// Apply header styling (optional)
$headerStyle = [
'font' => ['bold' => true],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['argb' => 'FFD3D3D3']],
];
$sheet->getStyle('A1:' . $sheet->getCellByColumnAndRow(count($headers), 1)->getColumn() . '1')->applyFromArray($headerStyle);
// 4. Populate Data Rows
$rowNum = 2; // Start from the second row
foreach ($logs as $log) {
$sheet->setCellValue('A' . $rowNum, $log['timestamp']);
$sheet->setCellValue('B' . $rowNum, $log['server_name']);
$sheet->setCellValue('C' . $rowNum, $log['status_code']);
$sheet->setCellValue('D' . $rowNum, $log['response_time_ms'] ?? ''); // Handle null values
$sheet->setCellValue('E' . $rowNum, $log['error_message'] ?? ''); // Handle null values
$rowNum++;
}
// 5. Auto-size Columns for better readability
foreach (range('A', $sheet->getHighestDataColumn()) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
// 6. Create the Writer and Save the File
$writer = new Xlsx($spreadsheet);
try {
$writer->save($outputFilePath);
return true;
} catch (\Exception $e) {
error_log("Failed to save spreadsheet report to {$outputFilePath}: " . $e->getMessage());
return false;
}
}
Integrating with WordPress
To make this report generation accessible, we can hook it into WordPress's functionality. Two common approaches are:
- Admin Page Button: Create a custom admin page where users can click a button to generate and download the report.
- WP-Cron Job: Schedule the report generation to run automatically at regular intervals (e.g., daily, weekly).
Example: Admin Page Button for Manual Generation
This example shows how to add a simple admin page with a button to trigger the report generation. The generated file will be saved to the WordPress uploads directory.
// Add this to your plugin's main file or an included file
add_action('admin_menu', 'add_server_status_report_menu');
function add_server_status_report_menu() {
add_management_page(
'Server Status Report',
'Server Status Report',
'manage_options', // Capability required to access
'server-status-report',
'render_server_status_report_page'
);
}
function render_server_status_report_page() {
?>
Server Status Compliance Report
Click the button below to generate the latest server status compliance report.
$_POST['start_date'], 'server_name' => $_POST['server_name']]
if (generate_server_status_report($outputFilePath, $filters)) {
echo 'Report generated successfully: ' . esc_html($fileName) . '
';
} else {
echo 'Failed to generate report.
';
}
}
?>
Example: WP-Cron Job for Automated Reporting
To automate this, we can use WP-Cron. First, schedule a custom cron event. Then, create a function that runs on that event.
// Add to your plugin's main file or an included file
// 1. Schedule the event on plugin activation
register_activation_hook(__FILE__, 'schedule_server_status_report_cron');
function schedule_server_status_report_cron() {
if (!wp_next_scheduled('daily_server_status_report')) {
// Schedule to run daily at 2 AM
wp_schedule_event(time(), 'daily', 'daily_server_status_report');
}
}
// 2. Hook the function to the scheduled event
add_action('daily_server_status_report', 'run_automated_server_status_report');
function run_automated_server_status_report() {
$uploadDir = wp_upload_dir();
$reportDir = trailingslashit($uploadDir['basedir']) . 'server-reports/';
if (!file_exists($reportDir)) {
wp_mkdir_p($reportDir);
}
$fileName = 'server_status_report_' . date('Ymd') . '.xlsx'; // Daily report, no time needed
$outputFilePath = $reportDir . $fileName;
// Define filters for the automated report (e.g., last 24 hours)
$filters = [
'start_date' => date('Y-m-d', strtotime('-1 day')),
'end_date' => date('Y-m-d'),
];
if (generate_server_status_report($outputFilePath, $filters)) {
// Optionally send an email notification on success
// wp_mail('[email protected]', 'Server Report Generated', 'The daily server status report was generated successfully.');
} else {
// Optionally send an email notification on failure
// wp_mail('[email protected]', 'Server Report Generation FAILED', 'The daily server status report failed to generate.');
}
}
// 3. Unschedule the event on plugin deactivation
register_deactivation_hook(__FILE__, 'unschedule_server_status_report_cron');
function unschedule_server_status_report_cron() {
$timestamp = wp_next_scheduled('daily_server_status_report');
if ($timestamp) {
wp_unschedule_event($timestamp, 'daily_server_status_report');
}
}
// Ensure the generate_server_status_report function is defined or included before this.
// Also ensure the Composer autoloader is included.
Advanced Considerations and Best Practices
- Error Handling: Implement robust error handling for database queries and file operations. Log errors to the WordPress debug log or a custom error log.
- Security: Sanitize all user inputs if using an admin page. Use nonces to prevent CSRF attacks. Ensure the generated reports are stored in a secure location, and consider access controls if they contain sensitive information.
- Performance: For very large log datasets, consider fetching data in batches or optimizing the SQL query. PHP-Spreadsheet can consume significant memory for large files; monitor resource usage.
- File Management: Implement a strategy for managing old report files to prevent disk space exhaustion (e.g., delete reports older than X days).
- Configuration: Allow users to configure report parameters (date ranges, servers, output format) through the WordPress admin interface.
- Alternative Formats: PHP-Spreadsheet supports various formats beyond XLSX, including CSV, PDF, HTML, and ODS. Adapt the writer class accordingly if other formats are required.
By integrating PHP-Spreadsheet into your WordPress development workflow, you can create powerful, automated reporting solutions that significantly reduce manual effort and improve compliance adherence for custom internal systems.
Leveraging PHP-Spreadsheet for Automated Server Log Compliance Reporting
Many internal applications, especially those with custom logging mechanisms, require periodic compliance reporting. This often involves extracting specific data points from server logs and presenting them in a structured, easily digestible format like a spreadsheet. Manually generating these reports is time-consuming and error-prone. This guide details how to implement an automated compliance reporting system within a WordPress environment using the powerful PHP-Spreadsheet library to export custom server status log data.
Setting Up the PHP-Spreadsheet Library
The first step is to integrate the PHP-Spreadsheet library into your WordPress project. The most robust way to manage external libraries in WordPress is through Composer. If you don't have a composer.json file in your theme or plugin root, create one. Then, add PHP-Spreadsheet as a dependency.
Navigate to your theme or plugin directory in your terminal and run:
composer require phpoffice/phpspreadsheet
This command will download the library and its dependencies into a vendor directory and update your composer.json and composer.lock files. You'll then need to include the Composer autoloader in your WordPress plugin or theme's main file.
// In your plugin's main file (e.g., my-custom-plugin.php) require_once __DIR__ . '/vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // ... rest of your plugin code
Designing the Custom Log Structure
For this example, let's assume your custom server status logs are stored in a custom database table, perhaps named wp_server_status_logs. Each entry might contain fields like log_id, timestamp, server_name, status_code, response_time_ms, and error_message.
A typical log entry might look like this in the database:
-- Example table structure
CREATE TABLE wp_server_status_logs (
log_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME NOT NULL,
server_name VARCHAR(255) NOT NULL,
status_code INT NOT NULL,
response_time_ms INT NULL,
error_message TEXT NULL
);
Implementing the Report Generation Logic
We'll create a function that queries the log data, processes it, and then uses PHP-Spreadsheet to generate an XLSX file. This function could be triggered by a WordPress cron job or a custom admin page button.
Here's a PHP function that accomplishes this:
/**
* Generates a compliance report from server status logs.
*
* @param string $outputFilePath The full path where the XLSX file will be saved.
* @param array $filters Optional array of filters (e.g., 'start_date', 'end_date', 'server_name').
* @return bool True on success, false on failure.
*/
function generate_server_status_report(string $outputFilePath, array $filters = []): bool
{
global $wpdb;
$tableName = $wpdb->prefix . 'server_status_logs';
// 1. Fetch Log Data with Filters
$query = "SELECT timestamp, server_name, status_code, response_time_ms, error_message FROM {$tableName}";
$whereClauses = [];
$queryArgs = [];
if (!empty($filters['start_date'])) {
$whereClauses[] = "timestamp >= %s";
$queryArgs[] = sanitize_text_field($filters['start_date']) . ' 00:00:00';
}
if (!empty($filters['end_date'])) {
$whereClauses[] = "timestamp <= %s";
$queryArgs[] = sanitize_text_field($filters['end_date']) . ' 23:59:59';
}
if (!empty($filters['server_name'])) {
$whereClauses[] = "server_name = %s";
$queryArgs[] = sanitize_text_field($filters['server_name']);
}
if (!empty($whereClauses)) {
$query .= " WHERE " . implode(' AND ', $whereClauses);
}
$query .= " ORDER BY timestamp ASC";
$logs = $wpdb->get_results($wpdb->prepare($query, $queryArgs), ARRAY_A);
if ($logs === null) {
error_log("Failed to fetch server status logs: " . $wpdb->last_error);
return false;
}
// 2. Initialize PHP-Spreadsheet
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 3. Set Headers
$headers = ['Timestamp', 'Server Name', 'Status Code', 'Response Time (ms)', 'Error Message'];
$sheet->fromArray([$headers], NULL, 'A1');
// Apply header styling (optional)
$headerStyle = [
'font' => ['bold' => true],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['argb' => 'FFD3D3D3']],
];
$sheet->getStyle('A1:' . $sheet->getCellByColumnAndRow(count($headers), 1)->getColumn() . '1')->applyFromArray($headerStyle);
// 4. Populate Data Rows
$rowNum = 2; // Start from the second row
foreach ($logs as $log) {
$sheet->setCellValue('A' . $rowNum, $log['timestamp']);
$sheet->setCellValue('B' . $rowNum, $log['server_name']);
$sheet->setCellValue('C' . $rowNum, $log['status_code']);
$sheet->setCellValue('D' . $rowNum, $log['response_time_ms'] ?? ''); // Handle null values
$sheet->setCellValue('E' . $rowNum, $log['error_message'] ?? ''); // Handle null values
$rowNum++;
}
// 5. Auto-size Columns for better readability
foreach (range('A', $sheet->getHighestDataColumn()) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
// 6. Create the Writer and Save the File
$writer = new Xlsx($spreadsheet);
try {
$writer->save($outputFilePath);
return true;
} catch (\Exception $e) {
error_log("Failed to save spreadsheet report to {$outputFilePath}: " . $e->getMessage());
return false;
}
}
Integrating with WordPress
To make this report generation accessible, we can hook it into WordPress's functionality. Two common approaches are:
- Admin Page Button: Create a custom admin page where users can click a button to generate and download the report.
- WP-Cron Job: Schedule the report generation to run automatically at regular intervals (e.g., daily, weekly).
Example: Admin Page Button for Manual Generation
This example shows how to add a simple admin page with a button to trigger the report generation. The generated file will be saved to the WordPress uploads directory.
// Add this to your plugin's main file or an included file
add_action('admin_menu', 'add_server_status_report_menu');
function add_server_status_report_menu() {
add_management_page(
'Server Status Report',
'Server Status Report',
'manage_options', // Capability required to access
'server-status-report',
'render_server_status_report_page'
);
}
function render_server_status_report_page() {
?>
Server Status Compliance Report
Click the button below to generate the latest server status compliance report.
$_POST['start_date'], 'server_name' => $_POST['server_name']]
if (generate_server_status_report($outputFilePath, $filters)) {
echo 'Report generated successfully: ' . esc_html($fileName) . '
';
} else {
echo 'Failed to generate report.
';
}
}
?>
Example: WP-Cron Job for Automated Reporting
To automate this, we can use WP-Cron. First, schedule a custom cron event. Then, create a function that runs on that event.
// Add to your plugin's main file or an included file
// 1. Schedule the event on plugin activation
register_activation_hook(__FILE__, 'schedule_server_status_report_cron');
function schedule_server_status_report_cron() {
if (!wp_next_scheduled('daily_server_status_report')) {
// Schedule to run daily at 2 AM
wp_schedule_event(time(), 'daily', 'daily_server_status_report');
}
}
// 2. Hook the function to the scheduled event
add_action('daily_server_status_report', 'run_automated_server_status_report');
function run_automated_server_status_report() {
$uploadDir = wp_upload_dir();
$reportDir = trailingslashit($uploadDir['basedir']) . 'server-reports/';
if (!file_exists($reportDir)) {
wp_mkdir_p($reportDir);
}
$fileName = 'server_status_report_' . date('Ymd') . '.xlsx'; // Daily report, no time needed
$outputFilePath = $reportDir . $fileName;
// Define filters for the automated report (e.g., last 24 hours)
$filters = [
'start_date' => date('Y-m-d', strtotime('-1 day')),
'end_date' => date('Y-m-d'),
];
if (generate_server_status_report($outputFilePath, $filters)) {
// Optionally send an email notification on success
// wp_mail('[email protected]', 'Server Report Generated', 'The daily server status report was generated successfully.');
} else {
// Optionally send an email notification on failure
// wp_mail('[email protected]', 'Server Report Generation FAILED', 'The daily server status report failed to generate.');
}
}
// 3. Unschedule the event on plugin deactivation
register_deactivation_hook(__FILE__, 'unschedule_server_status_report_cron');
function unschedule_server_status_report_cron() {
$timestamp = wp_next_scheduled('daily_server_status_report');
if ($timestamp) {
wp_unschedule_event($timestamp, 'daily_server_status_report');
}
}
// Ensure the generate_server_status_report function is defined or included before this.
// Also ensure the Composer autoloader is included.
Advanced Considerations and Best Practices
- Error Handling: Implement robust error handling for database queries and file operations. Log errors to the WordPress debug log or a custom error log.
- Security: Sanitize all user inputs if using an admin page. Use nonces to prevent CSRF attacks. Ensure the generated reports are stored in a secure location, and consider access controls if they contain sensitive information.
- Performance: For very large log datasets, consider fetching data in batches or optimizing the SQL query. PHP-Spreadsheet can consume significant memory for large files; monitor resource usage.
- File Management: Implement a strategy for managing old report files to prevent disk space exhaustion (e.g., delete reports older than X days).
- Configuration: Allow users to configure report parameters (date ranges, servers, output format) through the WordPress admin interface.
- Alternative Formats: PHP-Spreadsheet supports various formats beyond XLSX, including CSV, PDF, HTML, and ODS. Adapt the writer class accordingly if other formats are required.
By integrating PHP-Spreadsheet into your WordPress development workflow, you can create powerful, automated reporting solutions that significantly reduce manual effort and improve compliance adherence for custom internal systems.