sanitize_key( $code ), 'status' => sanitize_key( $status ), ) ); } wp_safe_redirect( add_query_arg( array( 'page' => $page, ), admin_url( 'admin.php' ) ) ); exit; } /** * Print admin notice stored for the current user. */ public static function render_notice() { if ( ! current_user_can( self::capability() ) ) { return; } $user_id = get_current_user_id(); $notice = get_user_meta( $user_id, 'amar_admin_notice', true ); if ( empty( $notice ) || ! is_array( $notice ) ) { return; } delete_user_meta( $user_id, 'amar_admin_notice' ); $code = isset( $notice['code'] ) ? sanitize_key( $notice['code'] ) : ''; $status = isset( $notice['status'] ) ? sanitize_key( $notice['status'] ) : 'success'; $messages = array( 'settings_saved' => __( 'Settings saved.', 'agency-maintenance-activity-reports' ), 'note_added' => __( 'Manual note added.', 'agency-maintenance-activity-reports' ), 'event_deleted' => __( 'Activity entry deleted.', 'agency-maintenance-activity-reports' ), 'report_sent' => __( 'Report email sent to the client.', 'agency-maintenance-activity-reports' ), 'invalid_email' => __( 'Please enter a valid client email address.', 'agency-maintenance-activity-reports' ), 'mail_failed' => __( 'The report email could not be sent.', 'agency-maintenance-activity-reports' ), 'invalid_note' => __( 'Please enter a manual note before saving.', 'agency-maintenance-activity-reports' ), 'permission_denied'=> __( 'You do not have permission to perform this action.', 'agency-maintenance-activity-reports' ), ); $message = isset( $messages[ $code ] ) ? $messages[ $code ] : ''; if ( empty( $message ) ) { return; } $class = ( 'error' === $status ) ? 'notice notice-error' : 'notice notice-success'; printf( '

%2$s

', esc_attr( $class ), esc_html( $message ) ); } /** * Verify admin POST request. * * @param string $action Action name. * @param string $nonce_field Nonce field name. */ private static function verify_post_request( $action, $nonce_field ) { if ( ! current_user_can( self::capability() ) ) { wp_die( esc_html__( 'You do not have permission to perform this action.', 'agency-maintenance-activity-reports' ) ); } check_admin_referer( $action, $nonce_field ); } /** * Save settings handler. */ public static function handle_save_settings() { self::verify_post_request( 'amar_save_settings', 'amar_settings_nonce' ); // Nonce verified in verify_post_request(). $input = wp_unslash( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing AMAR_Settings::save( $input ); self::redirect_with_notice( AMAR_PLUGIN_SLUG . '-settings', 'success', 'settings_saved' ); } /** * Add manual note handler. */ public static function handle_add_manual_note() { self::verify_post_request( 'amar_add_manual_note', 'amar_manual_note_nonce' ); // Nonce verified in verify_post_request(). $note = isset( $_POST['manual_note'] ) ? sanitize_textarea_field( wp_unslash( $_POST['manual_note'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( empty( $note ) ) { self::redirect_with_notice( AMAR_PLUGIN_SLUG . '-activity', 'error', 'invalid_note' ); } AMAR_Tracker::log_event( array( 'event_type' => 'manual_note', 'object_type' => 'note', 'object_name' => __( 'Manual maintenance note', 'agency-maintenance-activity-reports' ), 'notes' => $note, ) ); self::redirect_with_notice( AMAR_PLUGIN_SLUG . '-activity', 'success', 'note_added' ); } /** * Delete event handler. */ public static function handle_delete_event() { self::verify_post_request( 'amar_delete_event', 'amar_delete_event_nonce' ); // Nonce verified in verify_post_request(). $event_id = isset( $_POST['event_id'] ) ? absint( $_POST['event_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( $event_id > 0 ) { AMAR_Tracker::delete_event( $event_id ); } self::redirect_with_notice( AMAR_PLUGIN_SLUG . '-activity', 'success', 'event_deleted' ); } /** * Extract report request args from POST. * * Caller must verify the request nonce before calling this method. * * @return array{preset:string,start:string,end:string} */ private static function get_report_request_args() { // Nonce must be verified by the caller before reading POST data. $preset = isset( $_POST['date_preset'] ) ? sanitize_key( wp_unslash( $_POST['date_preset'] ) ) : 'last_30_days'; // phpcs:ignore WordPress.Security.NonceVerification.Missing $start_raw = isset( $_POST['start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['start_date'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $end_raw = isset( $_POST['end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['end_date'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing $start = AMAR_Report::sanitize_date( $start_raw ); $end = AMAR_Report::sanitize_date( $end_raw ); return array( 'preset' => $preset, 'start' => $start, 'end' => $end, ); } /** * Send report handler. */ public static function handle_send_report() { self::verify_post_request( 'amar_send_report', 'amar_send_nonce' ); $args = self::get_report_request_args(); $report = AMAR_Report::build( $args['preset'], $args['start'], $args['end'] ); $result = AMAR_Mailer::send_report( $report ); if ( is_wp_error( $result ) ) { $code = 'amar_invalid_email' === $result->get_error_code() ? 'invalid_email' : 'mail_failed'; self::redirect_with_notice( AMAR_PLUGIN_SLUG . '-report', 'error', $code ); } self::redirect_with_notice( AMAR_PLUGIN_SLUG . '-report', 'success', 'report_sent' ); } /** * Preview report handler. */ public static function handle_preview_report() { self::verify_post_request( 'amar_preview_report', 'amar_preview_nonce' ); $args = self::get_report_request_args(); $report = AMAR_Report::build( $args['preset'], $args['start'], $args['end'] ); nocache_headers(); header( 'Content-Type: text/html; charset=utf-8' ); echo AMAR_Report::render_html( $report, false ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped exit; } /** * Dashboard page. */ public static function render_dashboard_page() { if ( ! current_user_can( self::capability() ) ) { return; } $recent_events = AMAR_Tracker::get_recent_events( 8 ); $settings = AMAR_Settings::get_all(); $today = current_time( 'Y-m-d' ); $month_start = gmdate( 'Y-m-01', strtotime( $today ) ); $month_count = AMAR_Tracker::count_events( $month_start, $today ); include AMAR_PLUGIN_DIR . 'templates/admin-dashboard.php'; } /** * Report page. */ public static function render_report_page() { if ( ! current_user_can( self::capability() ) ) { return; } $settings = AMAR_Settings::get_all(); include AMAR_PLUGIN_DIR . 'templates/admin-report.php'; } /** * Activity log page. */ public static function render_activity_page() { if ( ! current_user_can( self::capability() ) ) { return; } $today = current_time( 'Y-m-d' ); $start = gmdate( 'Y-m-d', strtotime( '-29 days', strtotime( $today ) ) ); $events = AMAR_Tracker::get_events( $start, $today, 200 ); include AMAR_PLUGIN_DIR . 'templates/admin-activity.php'; } /** * Settings page. */ public static function render_settings_page() { if ( ! current_user_can( self::capability() ) ) { return; } $settings = AMAR_Settings::get_all(); include AMAR_PLUGIN_DIR . 'templates/admin-settings.php'; } }