__( 'A collapsible tree of your pages.', 'content-trees' ), ) ); } /** * Render the widget using theme wrappers. * * @param array $args Tree options or theme widget wrappers. * @param array $instance Saved widget settings. */ public function widget( $args, $instance ) { $stored_title = $instance['title'] ?? __( 'Pages', 'content-trees' ); $title = is_string( $stored_title ) ? sanitize_text_field( $stored_title ) : __( 'Pages', 'content-trees' ); $title = apply_filters( 'widget_title', $title, $instance, $this->id_base ); $title = is_string( $title ) ? $title : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Theme-owned markup from register_sidebar(). echo $args['before_widget']; if ( '' !== $title ) { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Theme-owned title wrappers; filtered title is escaped separately. echo $args['before_title']; echo esc_html( $title ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Theme-owned title wrappers from register_sidebar(). echo $args['after_title']; } // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- render_pages() escapes labels, URLs and attributes at construction. echo render_pages( array_merge( $instance, array( 'title' => '' !== $title ? $title : __( 'Pages', 'content-trees' ), 'show_title' => false, ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Theme-owned markup from register_sidebar(). echo $args['after_widget']; } /** * Render the classic widget settings. * * @param array $instance Saved widget settings. */ public function form( $instance ) { $instance = pages_options( $instance ); $title = $instance['title']; $date_sort = in_array( $instance['sort_by'], array( 'date', 'modified' ), true ); ?>

page_selector( 'root', $instance['root'] ? array( $instance['root'] ) : array(), true ); ?>

>

>

>

page_selector( 'excluded_pages', $instance['excluded_pages'] ); ?>
'', 'root' => 0, 'auto_open' => false, 'excluded_pages' => array(), 'show_controls' => false, 'close_siblings' => false, ), $new_instance ) ); return array_intersect_key( $instance, array_flip( array( 'title', 'root', 'sort_by', 'order', 'auto_open', 'excluded_pages', 'show_controls', 'close_siblings' ) ) ); } /** * Render the shared searchable selector with page-specific labels. * * @param string $field Setting name. * @param int[] $ids Selected IDs. * @param bool $single Whether only one selection is allowed. */ private function page_selector( $field, $ids, $single = false ) { $remove = $single ? __( 'Clear start page', 'content-trees' ) : __( 'Remove page', 'content-trees' ); ?>