version = $version; } /** * CSS op de BoardIt-pagina's. * * @param string $hook Huidige beheerpagina. */ public function enqueue_styles( $hook ) { if ( strpos( $hook, 'boardit' ) === false ) { return; } wp_enqueue_style( 'boardit-admin', BOARDIT_PLUGIN_URL . 'admin/css/boardit-admin.css', array(), $this->version ); } /** * Scripts op de BoardIt-pagina's (per pagina wat nodig is). * * @param string $hook Huidige beheerpagina. */ public function enqueue_scripts( $hook ) { if ( strpos( $hook, 'boardit' ) === false ) { return; } // E-mailpagina: eigen script. if ( strpos( $hook, 'boardit-email' ) !== false ) { wp_enqueue_media(); wp_enqueue_script( 'boardit-admin-email', BOARDIT_PLUGIN_URL . 'admin/js/boardit-admin-email.js', array( 'jquery' ), $this->version, true ); wp_localize_script( 'boardit-admin-email', 'boarditEmail', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'boardit_admin_nonce' ), 'strings' => array( 'saved' => __( 'Settings saved!', 'boardit' ), 'error' => __( 'Something went wrong.', 'boardit' ), 'test_sent' => __( 'Test email sent!', 'boardit' ), 'test_error' => __( 'Test email could not be sent.', 'boardit' ), 'fill_address' => __( 'Please enter a recipient.', 'boardit' ), 'select_logo' => __( 'Choose logo', 'boardit' ), 'select_other_logo' => __( 'Choose different logo', 'boardit' ), 'use_image' => __( 'Use image', 'boardit' ), ), ) ); }//end if wp_enqueue_script( 'boardit-admin', BOARDIT_PLUGIN_URL . 'admin/js/boardit-admin.js', array( 'jquery', 'jquery-ui-sortable' ), ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? filemtime( BOARDIT_PLUGIN_DIR . 'admin/js/boardit-admin.js' ) : $this->version, true ); wp_localize_script( 'boardit-admin', 'boarditAdmin', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'boardit_admin_nonce' ), 'strings' => array( 'confirm_delete' => __( 'Are you sure you want to delete this?', 'boardit' ), 'confirm_block_member' => __( 'Are you sure you want to block this member?', 'boardit' ), 'confirm_unblock_member' => __( 'Are you sure you want to unblock this member?', 'boardit' ), 'confirm_seed' => __( 'Are you sure you want to create 50 test members? This cannot be undone.', 'boardit' ), 'saved' => __( 'Saved!', 'boardit' ), 'error' => __( 'Something went wrong.', 'boardit' ), 'blocked' => __( 'Blocked', 'boardit' ), 'active' => __( 'Active', 'boardit' ), 'block' => __( 'Block', 'boardit' ), 'unblock' => __( 'Unblock', 'boardit' ), 'seeding' => __( 'Creating test members…', 'boardit' ), 'confirm_delete_test' => __( 'Are you sure you want to delete all test members?', 'boardit' ), 'deleting_test' => __( 'Deleting test members…', 'boardit' ), ), ) ); } /** * Menu BoardIt met de subpagina's. */ public function add_admin_menus() { add_menu_page( __( 'BoardIt', 'boardit' ), 'BoardIt', 'manage_options', self::RESERVATIONS_PAGE, array( $this, 'page_reservations' ), 'dashicons-calendar-alt', 30 ); add_submenu_page( 'boardit', __( 'Reservations', 'boardit' ), __( 'Reservations', 'boardit' ), 'manage_options', self::RESERVATIONS_PAGE, array( $this, 'page_reservations' ) ); add_submenu_page( 'boardit', __( 'Manage courts', 'boardit' ), __( 'Courts', 'boardit' ), 'manage_options', 'boardit-courts', array( $this, 'page_courts' ) ); add_submenu_page( 'boardit', __( 'Member management', 'boardit' ), __( 'Members', 'boardit' ), 'manage_options', 'boardit-members', array( $this, 'page_members' ) ); add_submenu_page( 'boardit', __( 'E-mail', 'boardit' ), __( 'E-mail', 'boardit' ), 'manage_options', 'boardit-email', array( $this, 'page_email' ) ); /** * Extra pagina's (Pro): add_submenu_page( 'boardit', … ) met een positie. * Statistieken komt op plek 3 (na Leden), Vaste reserveringen op plek 5 (na E-mail). * * @param Boardit_Admin $admin Beheer. */ do_action( 'boardit_admin_menu', $this ); // Zonder Pro staan Statistieken en Vaste reserveringen ook in het menu, met uitleg en een link naar Pro. $upgrade = new Boardit_Admin_Upgrade(); if ( ! Boardit_Features::can( 'stats' ) ) { add_submenu_page( 'boardit', __( 'Statistics', 'boardit' ), __( 'Statistics', 'boardit' ), 'manage_options', 'boardit-stats', array( $upgrade, 'render_stats_preview' ), 3 ); } if ( ! Boardit_Features::can( 'fixed_reservations' ) ) { add_submenu_page( 'boardit', __( 'Fixed reservations', 'boardit' ), __( 'Fixed res.', 'boardit' ), 'manage_options', 'boardit-fixed', array( $upgrade, 'render_fixed_preview' ), 5 ); } // Wat Pro extra biedt; niet meer nodig zodra Pro actief is (dan staat Freemius' Account in het menu). if ( ! boardit_is_pro() ) { add_submenu_page( 'boardit', __( 'BoardIt Pro', 'boardit' ), __( 'BoardIt Pro', 'boardit' ), 'manage_options', Boardit_Admin_Upgrade::SLUG, array( $upgrade, 'render' ) ); } // Instellingen staat bewust als laatste in het submenu. add_submenu_page( 'boardit', __( 'Settings', 'boardit' ), __( 'Settings', 'boardit' ), 'manage_options', 'boardit-settings', array( $this, 'page_settings' ) ); } /** * Instellingen voor options.php (pagina's Instellingen en E-mail). */ public function register_settings() { register_setting( 'boardit_settings', 'boardit_open_time', array( 'sanitize_callback' => 'sanitize_text_field' ) ); register_setting( 'boardit_settings', 'boardit_close_time', array( 'sanitize_callback' => 'sanitize_text_field' ) ); register_setting( 'boardit_settings', 'boardit_max_advance_days', array( 'sanitize_callback' => 'absint' ) ); register_setting( 'boardit_settings', 'boardit_require_login', array( 'sanitize_callback' => 'absint' ) ); register_setting( 'boardit_settings', 'boardit_max_reservations', array( 'sanitize_callback' => 'absint' ) ); register_setting( 'boardit_settings', 'boardit_past_days', array( 'sanitize_callback' => 'absint' ) ); register_setting( 'boardit_settings', 'boardit_board_refresh_interval', array( 'sanitize_callback' => array( $this, 'sanitize_refresh_interval' ), ) ); // Kleurinstellingen. $color_options = array( 'boardit_color_primary', 'boardit_color_primary_hover', 'boardit_color_available_bg', 'boardit_color_available_text', 'boardit_color_available_border', 'boardit_color_reserved_bg', 'boardit_color_reserved_text', 'boardit_color_mine_bg', 'boardit_color_mine_text', 'boardit_color_mine_accent', 'boardit_color_past_bg', ); foreach ( $color_options as $option ) { register_setting( 'boardit_settings', $option, array( 'sanitize_callback' => 'sanitize_hex_color' ) ); } // E-mailinstellingen. register_setting( 'boardit_email_settings', 'boardit_email_from_name', array( 'sanitize_callback' => 'sanitize_text_field' ) ); register_setting( 'boardit_email_settings', 'boardit_email_from_address', array( 'sanitize_callback' => 'sanitize_email' ) ); register_setting( 'boardit_email_settings', 'boardit_email_booking_enabled', array( 'sanitize_callback' => 'absint' ) ); register_setting( 'boardit_email_settings', 'boardit_email_booking_subject', array( 'sanitize_callback' => 'sanitize_text_field' ) ); register_setting( 'boardit_email_settings', 'boardit_email_booking_body', array( 'sanitize_callback' => 'sanitize_textarea_field' ) ); register_setting( 'boardit_email_settings', 'boardit_email_cancel_enabled', array( 'sanitize_callback' => 'absint' ) ); register_setting( 'boardit_email_settings', 'boardit_email_cancel_subject', array( 'sanitize_callback' => 'sanitize_text_field' ) ); register_setting( 'boardit_email_settings', 'boardit_email_cancel_body', array( 'sanitize_callback' => 'sanitize_textarea_field' ) ); register_setting( 'boardit_email_settings', 'boardit_email_move_enabled', array( 'sanitize_callback' => 'absint' ) ); register_setting( 'boardit_email_settings', 'boardit_email_move_subject', array( 'sanitize_callback' => 'sanitize_text_field' ) ); register_setting( 'boardit_email_settings', 'boardit_email_move_body', array( 'sanitize_callback' => 'sanitize_textarea_field' ) ); } /** * Sanitiseert het interval (in seconden) waarmee het bord automatisch controleert * op wijzigingen van andere gebruikers. 0 betekent uitgeschakeld; een waarde * daarboven wordt geclamped tussen 5 en 300 seconden om te voorkomen dat de * server onnodig vaak wordt belast door een te lage waarde. * * @param int|string $val Ingevoerde waarde. * @return int */ public function sanitize_refresh_interval( $val ) { $val = absint( $val ); if ( 0 === $val ) { return 0; } return max( 5, min( 300, $val ) ); } /** * Valideert een datum uit de querystring (Y-m-d). Ongeldige of lege invoer * valt terug op vandaag in de tijdzone van de site. * * @param mixed $raw Waarde uit de querystring. * @return string */ public static function sanitize_admin_date( $raw ): string { $raw = is_string( $raw ) ? sanitize_text_field( wp_unslash( $raw ) ) : ''; $date = DateTime::createFromFormat( '!Y-m-d', $raw, wp_timezone() ); if ( $date && $date->format( 'Y-m-d' ) === $raw ) { return $raw; } return current_time( 'Y-m-d' ); } /** * Verschuift een Y-m-d-datum met een aantal dagen (zomer-/wintertijdveilig). * * @param string $date Datum (Y-m-d). * @param int $days Aantal dagen (negatief = terug). * @return string */ public static function shift_date( string $date, int $days ): string { $dt = DateTimeImmutable::createFromFormat( '!Y-m-d', $date, wp_timezone() ); if ( ! $dt ) { $dt = new DateTimeImmutable( current_time( 'Y-m-d' ), wp_timezone() ); } return $dt->modify( sprintf( '%+d day', $days ) )->format( 'Y-m-d' ); } /** * URL naar de Reserveringen-pagina voor een bepaalde datum. * * @param string $date Datum (Y-m-d). * @return string */ public static function get_reservations_url( string $date ): string { return add_query_arg( array( 'page' => self::RESERVATIONS_PAGE, 'boardit_date' => $date, ), admin_url( 'admin.php' ) ); } /** * Pagina Reserveringen (per dag, met datumnavigatie). */ public function page_reservations() { if ( ! current_user_can( 'manage_options' ) ) { return; } // Alleen-lezen navigatie: geen nonce nodig; de datum wordt strikt gevalideerd. $date = self::sanitize_admin_date( isset( $_GET['boardit_date'] ) ? sanitize_text_field( wp_unslash( $_GET['boardit_date'] ) ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $prev_day = self::shift_date( $date, -1 ); $next_day = self::shift_date( $date, 1 ); $today = current_time( 'Y-m-d' ); $courts = Boardit_DB::get_courts( false ); $reservations = Boardit_DB::get_reservations_for_date( $date ); include BOARDIT_PLUGIN_DIR . 'admin/partials/boardit-admin-reservations.php'; } /** * Pagina Banen. */ public function page_courts() { $courts = Boardit_DB::get_courts( false ); include BOARDIT_PLUGIN_DIR . 'admin/partials/boardit-admin-courts.php'; } /** * Pagina Leden (met zoeken). */ public function page_members() { if ( ! current_user_can( 'manage_options' ) ) { return; } // Alleen-lezen zoekopdracht: geen nonce nodig. $search = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $members = Boardit_DB::get_members( array( 'search' => $search ) ); include BOARDIT_PLUGIN_DIR . 'admin/partials/boardit-admin-members.php'; } /** * Pagina Instellingen. */ public function page_settings() { include BOARDIT_PLUGIN_DIR . 'admin/partials/boardit-admin-settings.php'; } /** * Pagina E-mail. */ public function page_email() { include BOARDIT_PLUGIN_DIR . 'admin/partials/boardit-admin-email.php'; } // ------------------------------------------------------------------------- // E-mail AJAX // ------------------------------------------------------------------------- /** * AJAX: e-mailinstellingen opslaan. */ public function ajax_save_email_settings() { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Access denied.', 'boardit' ) ) ); } update_option( 'boardit_email_from_name', sanitize_text_field( wp_unslash( $_POST['from_name'] ?? '' ) ) ); update_option( 'boardit_email_from_address', sanitize_email( wp_unslash( $_POST['from_address'] ?? '' ) ) ); update_option( 'boardit_email_booking_enabled', absint( $_POST['booking_enabled'] ?? 0 ) ); update_option( 'boardit_email_booking_subject', sanitize_text_field( wp_unslash( $_POST['booking_subject'] ?? '' ) ) ); update_option( 'boardit_email_booking_body', sanitize_textarea_field( wp_unslash( $_POST['booking_body'] ?? '' ) ) ); update_option( 'boardit_email_cancel_enabled', absint( $_POST['cancel_enabled'] ?? 0 ) ); update_option( 'boardit_email_cancel_subject', sanitize_text_field( wp_unslash( $_POST['cancel_subject'] ?? '' ) ) ); update_option( 'boardit_email_cancel_body', sanitize_textarea_field( wp_unslash( $_POST['cancel_body'] ?? '' ) ) ); update_option( 'boardit_email_move_enabled', absint( $_POST['move_enabled'] ?? 0 ) ); update_option( 'boardit_email_move_subject', sanitize_text_field( wp_unslash( $_POST['move_subject'] ?? '' ) ) ); update_option( 'boardit_email_move_body', sanitize_textarea_field( wp_unslash( $_POST['move_body'] ?? '' ) ) ); // Club logo. $logo_id = absint( $_POST['logo_id'] ?? 0 ); update_option( 'boardit_email_logo_id', $logo_id ); /** * Na het opslaan van de e-mailinstellingen (nonce en rechten zijn gecontroleerd). * Pro slaat hier de sponsorlogo's op. */ do_action( 'boardit_save_email_settings' ); wp_send_json_success( array( 'message' => __( 'Settings saved!', 'boardit' ) ) ); } /** * AJAX: testmail versturen. */ public function ajax_test_email() { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Access denied.', 'boardit' ) ) ); } $to = sanitize_email( wp_unslash( $_POST['to'] ?? '' ) ); $template = sanitize_text_field( wp_unslash( $_POST['template'] ?? 'booking' ) ); if ( empty( $to ) || ! is_email( $to ) ) { wp_send_json_error( array( 'message' => __( 'Invalid email address.', 'boardit' ) ) ); } $result = Boardit_Mailer::send_test( $to, $template ); if ( is_wp_error( $result ) ) { wp_send_json_error( array( 'message' => $result->get_error_message() ) ); } wp_send_json_success( array( 'message' => __( 'Test email sent!', 'boardit' ) ) ); } // ------------------------------------------------------------------------- // Baan AJAX // ------------------------------------------------------------------------- /** * AJAX: baan opslaan (nieuw of bewerken). Geen limiet op het aantal banen. */ public function ajax_save_court() { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Access denied.', 'boardit' ) ) ); } $id = intval( $_POST['court_id'] ?? 0 ); $sport_type = sanitize_text_field( wp_unslash( $_POST['sport_type'] ?? 'tennis' ) ); $allowed_types = array( 'tennis', 'padel', 'pickleball' ); if ( ! in_array( $sport_type, $allowed_types, true ) ) { $sport_type = 'tennis'; } // Standaarden per sporttype. $defaults_per_type = array( 'tennis' => array( 'min' => 1, 'max' => 4, 'slot' => 0, ), 'padel' => array( 'min' => 4, 'max' => 4, 'slot' => 90, ), 'pickleball' => array( 'min' => 2, 'max' => 4, 'slot' => 60, ), ); $type_defaults = $defaults_per_type[ $sport_type ]; $min_players = isset( $_POST['min_players'] ) ? intval( $_POST['min_players'] ) : $type_defaults['min']; $max_players = isset( $_POST['max_players'] ) ? intval( $_POST['max_players'] ) : $type_defaults['max']; $slot_minutes = isset( $_POST['slot_minutes'] ) ? intval( $_POST['slot_minutes'] ) : $type_defaults['slot']; // Grenzen bewaken. $min_players = max( 1, min( 4, $min_players ) ); $max_players = max( $min_players, min( 4, $max_players ) ); $slot_minutes = max( 0, $slot_minutes ); // Tennis heeft altijd variabele duur; forceer 0 om fouten te voorkomen. if ( 'tennis' === $sport_type ) { $slot_minutes = 0; } // 15 minuten extra: alleen voor tennisbanen; padel/pickleball altijd uit. $allow_extra_slot = ( 'tennis' === $sport_type && ! empty( $_POST['allow_extra_slot'] ) ) ? 1 : 0; $data = array( 'name' => sanitize_text_field( wp_unslash( $_POST['name'] ?? '' ) ), 'description' => sanitize_textarea_field( wp_unslash( $_POST['description'] ?? '' ) ), 'is_active' => intval( $_POST['is_active'] ?? 1 ), 'sort_order' => intval( $_POST['sort_order'] ?? 0 ), 'sport_type' => $sport_type, 'min_players' => $min_players, 'max_players' => $max_players, 'slot_minutes' => $slot_minutes, 'allow_extra_slot' => $allow_extra_slot, ); if ( empty( $data['name'] ) ) { wp_send_json_error( array( 'message' => __( 'Name is required.', 'boardit' ) ) ); } if ( $id > 0 ) { $result = Boardit_DB::update_court( $id, $data ); } else { $id = Boardit_DB::insert_court( $data ); } wp_send_json_success( array( 'court_id' => $id, 'message' => __( 'Court saved!', 'boardit' ), ) ); } /** * AJAX: baan verwijderen. */ public function ajax_delete_court() { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error(); } $id = intval( $_POST['court_id'] ?? 0 ); Boardit_DB::delete_court( $id ); wp_send_json_success( array( 'message' => __( 'Court deleted.', 'boardit' ) ) ); } /** * AJAX: volgorde van de banen opslaan (slepen). */ public function ajax_reorder_courts() { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Access denied.', 'boardit' ) ) ); } // JSON-lijst met baan-ID's; elk ID wordt hieronder met intval() gesaneerd. $order = json_decode( isset( $_POST['order'] ) ? wp_unslash( $_POST['order'] ) : '[]', true ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( ! is_array( $order ) || empty( $order ) ) { wp_send_json_error( array( 'message' => __( 'Invalid order.', 'boardit' ) ) ); } foreach ( $order as $i => $id ) { Boardit_DB::update_court( intval( $id ), array( 'sort_order' => $i ) ); } wp_send_json_success( array( 'message' => __( 'Order saved!', 'boardit' ) ) ); } /** * AJAX: reservering annuleren vanuit het beheer. */ public function ajax_admin_cancel() { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error(); } $id = intval( $_POST['reservation_id'] ?? 0 ); $result = Boardit_Reservation::cancel( $id ); if ( is_wp_error( $result ) ) { wp_send_json_error( array( 'message' => $result->get_error_message() ) ); } wp_send_json_success( array( 'message' => __( 'Reservation cancelled.', 'boardit' ) ) ); } // ------------------------------------------------------------------------- // Leden AJAX // ------------------------------------------------------------------------- /** * AJAX: lid blokkeren of deblokkeren. */ public function ajax_block_member() { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Access denied.', 'boardit' ) ) ); } $user_id = intval( $_POST['user_id'] ?? 0 ); $blocked = intval( $_POST['blocked'] ?? 1 ); if ( $user_id <= 0 ) { wp_send_json_error( array( 'message' => __( 'Invalid user ID.', 'boardit' ) ) ); } Boardit_DB::set_member_blocked( $user_id, (bool) $blocked ); $message = $blocked ? __( 'Member blocked.', 'boardit' ) : __( 'Member unblocked.', 'boardit' ); wp_send_json_success( array( 'message' => $message, 'blocked' => $blocked, 'user_id' => $user_id, ) ); } /** * Maak 50 testleden aan voor demo- en testdoeleinden. */ public function ajax_seed_members() { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Access denied.', 'boardit' ) ) ); } $voornamen = array( 'Emma', 'Liam', 'Sofia', 'Noah', 'Olivia', 'Lucas', 'Mia', 'Daan', 'Ava', 'Finn', 'Noor', 'Lars', 'Lisa', 'Tom', 'Sara', 'Jasper', 'Anna', 'Max', 'Julie', 'Thijs', 'Eva', 'Bram', 'Roos', 'Pieter', 'Laura', 'Kees', 'Amy', 'Sven', 'Fleur', 'Ruben', 'Iris', 'Joost', 'Lotte', 'Wout', 'Hanna', 'Niels', 'Amber', 'Rick', 'Eline', 'Job', 'Vera', 'Tim', 'Fenna', 'Stan', 'Maud', 'Robin', 'Stien', 'Arjan', 'Nienke', 'Boris', ); $achternamen = array( 'de Vries', 'Jansen', 'de Boer', 'van den Berg', 'Visser', 'Smit', 'Meijer', 'Bakker', 'Janssen', 'Bos', 'Vos', 'Peters', 'Hendriks', 'van Leeuwen', 'Dekker', 'Brouwer', 'de Wit', 'Dijkstra', 'Peeters', 'de Graaf', 'van Dijk', 'Mulder', 'de Jong', 'Willems', 'Linden', 'Vermeer', 'Hoekstra', 'Koster', 'Schouten', 'Prins', ); $created = 0; $skipped = 0; for ( $i = 0; $i < 50; $i++ ) { $voornaam = $voornamen[ $i % count( $voornamen ) ]; $achternaam = $achternamen[ $i % count( $achternamen ) ]; $suffix = $i > 0 ? $i : ''; $email = strtolower( remove_accents( $voornaam ) . '.' . remove_accents( str_replace( array( ' ', "'" ), '-', $achternaam ) ) . $suffix . '@boardit-test.local' ); if ( email_exists( $email ) ) { ++$skipped; continue; } $username = sanitize_user( strtolower( remove_accents( $voornaam ) . '.' . remove_accents( str_replace( array( ' ', "'" ), '-', $achternaam ) ) . $suffix ), true ); if ( username_exists( $username ) ) { $username .= '_' . wp_rand( 10, 99 ); } $result = wp_insert_user( array( 'user_login' => $username, 'user_email' => $email, 'user_pass' => wp_generate_password( 16, true ), 'display_name' => $voornaam . ' ' . $achternaam, 'role' => 'tennisclub_member', ) ); if ( ! is_wp_error( $result ) ) { update_user_meta( $result, 'boardit_test_user', 1 ); ++$created; } else { ++$skipped; } }//end for wp_send_json_success( array( 'message' => sprintf( /* translators: 1: aantal aangemaakt, 2: aantal overgeslagen */ __( '%1$d test members created, %2$d skipped (already exist).', 'boardit' ), $created, $skipped ), 'created' => $created, 'skipped' => $skipped, ) ); } /** * Verwijder alle testleden (meta boardit_test_user = 1). */ public function ajax_delete_test_members(): void { check_ajax_referer( 'boardit_admin_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'Access denied.', 'boardit' ) ) ); return; } // phpcs:disable WordPress.DB.SlowDBQuery -- eenmalige beheeractie: alleen de aangemaakte testleden. $users = get_users( array( 'meta_key' => 'boardit_test_user', 'meta_value' => 1, 'fields' => 'ID', 'number' => -1, ) ); // phpcs:enable WordPress.DB.SlowDBQuery $deleted = 0; foreach ( $users as $uid ) { if ( wp_delete_user( (int) $uid ) ) { ++$deleted; } } wp_send_json_success( array( 'message' => sprintf( /* translators: %d: aantal verwijderde testleden */ _n( '%d test member deleted.', '%d test members deleted.', $deleted, 'boardit' ), $deleted ), 'deleted' => $deleted, ) ); } }