__( 'A compact month grid that highlights dates with events.', 'agenticdaisy-calendar' ), 'classname' => 'webcal-mini-calendar-widget', ] ); } /** * Front-end display of widget. * * The `$args['before_widget']`, `$args['before_title']`, * `$args['after_title']`, and `$args['after_widget']` values are * echoed unescaped. This is the canonical WordPress widget pattern * documented in the Widgets API handbook * (https://developer.wordpress.org/themes/functionality/widgets/): * those values are set by the active theme's `register_sidebar()` * call (core-supplied or theme-supplied HTML, e.g. * `
`) and are intended to contain * trusted markup. Escaping them breaks every theme. User-controlled * content inside the widget (`$title`, `$calendar_url`) is still * properly escaped with `esc_html()` / `esc_url()` / `esc_attr()`. * * @param array $args Widget arguments provided by the theme. * @param array $instance Saved values from database. */ public function widget( $args, $instance ): void { $raw_title = $instance['title'] ?? ''; $title = is_string( $raw_title ) ? $raw_title : ''; $raw_url = $instance['calendar_url'] ?? ''; $calendar_url = is_string( $raw_url ) ? $raw_url : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Theme-provided wrapper HTML from register_sidebar(); canonical WP widget pattern (see method docblock). echo $args['before_widget']; if ( $title !== '' ) { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Theme-provided title wrapper HTML from register_sidebar(); canonical WP widget pattern (see method docblock). $title is esc_html()'d. echo $args['before_title'] . esc_html( $title ) . $args['after_title']; } wp_enqueue_style( 'webcal-frontend' ); wp_enqueue_script( 'webcal-mini-calendar' ); printf( '
', esc_attr( esc_url_raw( rest_url( 'webcal/v1/events' ) ) ), esc_attr( wp_create_nonce( 'wp_rest' ) ), esc_attr( esc_url( $calendar_url ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Theme-provided wrapper HTML from register_sidebar(); canonical WP widget pattern (see method docblock). echo $args['after_widget']; } /** * Back-end widget form. * * @param array $instance Previously saved values. */ public function form( $instance ): void { $raw_title = $instance['title'] ?? ''; $title = is_string( $raw_title ) && $raw_title !== '' ? sanitize_text_field( $raw_title ) : __( 'Calendar', 'agenticdaisy-calendar' ); $raw_url = $instance['calendar_url'] ?? ''; $calendar_url = is_string( $raw_url ) && $raw_url !== '' ? esc_url( $raw_url ) : ''; ?>

$new_instance Values just sent to be saved. * @param array $old_instance Previously saved values. * @return array */ public function update( $new_instance, $old_instance ): array { $raw_title = $new_instance['title'] ?? ''; $raw_url = $new_instance['calendar_url'] ?? ''; return [ 'title' => sanitize_text_field( is_string( $raw_title ) ? $raw_title : '' ), 'calendar_url' => esc_url_raw( is_string( $raw_url ) ? $raw_url : '' ), ]; } }