*/ public static function defaults(): array { return [ 'lead_time' => 2, // minimum hours from now. 'admin_email' => '', // falls back to get_option('admin_email'). 'from_name' => '', // falls back to blogname. 'reminder_hours' => 24, // send reminder N hours before (0 = off). 'webhook_url' => '', // POST reservation events here when set. 'turnstile_site' => '', // Cloudflare Turnstile site key (optional). 'turnstile_secret' => '', // Cloudflare Turnstile secret (optional). 'auto_confirm' => false, // Confirm online reservations without a call back. 'approval_party' => 8, // Parties larger than this always wait for the owner (0 = no limit). 'party_max' => 10, // Largest party that may book online; bigger ones call. 'gcal_client_id' => '', // Google OAuth client (the owner's own, from Google Cloud). 'gcal_client_secret' => '', 'gcal_calendar' => 'primary', // Calendar the reservations are copied to. 'gcal_push' => true, // Copy reservations to that calendar. 'gcal_busy_calendar' => '', // Busy events here block online booking ('' = off). 'hold_minutes' => 10, // A table is kept this long while the guest fills in the form (0 = off). 'restaurant_name' => '', // Shown on the booking page; falls back to blogname. 'restaurant_address' => '', 'restaurant_phone' => '', // Where a larger party is asked to call. 'restaurant_image' => 0, // Attachment id of the photo on the booking page. 'restaurant_map' => false, // Show a Google map of the address under the times. 'google_signin' => false, // "Sign in with Google" fills in the name and email (uses gcal_client_id). ]; } /** * @return array */ public static function all(): array { $stored = get_option( self::OPTION, [] ); if ( ! is_array( $stored ) ) { $stored = []; } // Keys an older version stored and this one no longer knows stay out. return array_replace( self::defaults(), array_intersect_key( $stored, self::defaults() ) ); } public static function get( string $key, mixed $fallback = null ): mixed { $all = self::all(); return $all[ $key ] ?? $fallback; } public static function seed(): void { if ( null === get_option( self::OPTION, null ) ) { add_option( self::OPTION, self::defaults() ); } } /** * @param array $input * @return array */ public static function update( array $input ): array { $old = self::all(); $new = array_replace( $old, self::sanitize( $input ) ); update_option( self::OPTION, $new ); return $new; } /** * @param array $input * @return array */ public static function sanitize( array $input ): array { $clean = []; if ( isset( $input['lead_time'] ) ) { $clean['lead_time'] = max( 0, min( 8760, absint( $input['lead_time'] ) ) ); } if ( isset( $input['admin_email'] ) ) { $clean['admin_email'] = sanitize_email( (string) $input['admin_email'] ); } if ( isset( $input['from_name'] ) ) { $clean['from_name'] = sanitize_text_field( (string) $input['from_name'] ); } if ( isset( $input['reminder_hours'] ) ) { $clean['reminder_hours'] = max( 0, min( 8760, absint( $input['reminder_hours'] ) ) ); } if ( isset( $input['webhook_url'] ) ) { $clean['webhook_url'] = esc_url_raw( (string) $input['webhook_url'] ); } if ( isset( $input['turnstile_site'] ) ) { $clean['turnstile_site'] = sanitize_text_field( (string) $input['turnstile_site'] ); } if ( isset( $input['turnstile_secret'] ) ) { $clean['turnstile_secret'] = sanitize_text_field( (string) $input['turnstile_secret'] ); } if ( isset( $input['auto_confirm'] ) ) { $clean['auto_confirm'] = (bool) $input['auto_confirm']; } if ( isset( $input['approval_party'] ) ) { $clean['approval_party'] = max( 0, min( 99, absint( $input['approval_party'] ) ) ); } if ( isset( $input['party_max'] ) ) { $clean['party_max'] = max( 1, min( 99, absint( $input['party_max'] ) ) ); } foreach ( [ 'gcal_client_id', 'gcal_client_secret', 'gcal_busy_calendar' ] as $key ) { if ( isset( $input[ $key ] ) ) { $clean[ $key ] = sanitize_text_field( (string) $input[ $key ] ); } } if ( isset( $input['gcal_calendar'] ) ) { $calendar = sanitize_text_field( (string) $input['gcal_calendar'] ); $clean['gcal_calendar'] = '' !== $calendar ? $calendar : 'primary'; } if ( isset( $input['gcal_push'] ) ) { $clean['gcal_push'] = (bool) $input['gcal_push']; } if ( isset( $input['hold_minutes'] ) ) { $clean['hold_minutes'] = max( 0, min( 30, absint( $input['hold_minutes'] ) ) ); } foreach ( [ 'restaurant_name', 'restaurant_address', 'restaurant_phone' ] as $key ) { if ( isset( $input[ $key ] ) ) { $clean[ $key ] = mb_substr( sanitize_text_field( (string) $input[ $key ] ), 0, 200 ); } } if ( isset( $input['restaurant_image'] ) ) { $image = absint( $input['restaurant_image'] ); $clean['restaurant_image'] = $image > 0 && wp_attachment_is_image( $image ) ? $image : 0; } foreach ( [ 'restaurant_map', 'google_signin' ] as $key ) { if ( isset( $input[ $key ] ) ) { $clean[ $key ] = (bool) $input[ $key ]; } } return $clean; } }