label) * display open | collapsible-open | collapsible-closed (collapsible =
) * show N > 0 → only the first N items of each list, the rest inside a nested *
  • ดูเพิ่ม (+k)
    • * class extra classes on the root element (sanitized per token) * * With every option at its default the output is exactly what the widgets printed before 0.4 (back-compat). * * @package AooShop */ defined( 'ABSPATH' ) || exit; class AooShop_Widget_Frame { const TAGS = array( 'h2', 'h3', 'h4', 'none' ); const DISPLAYS = array( 'open', 'collapsible-open', 'collapsible-closed' ); /** Frame atts shared by every browse shortcode (merged into each widget's own defaults). */ public static function defaults() { return array( 'heading' => '', 'heading_tag' => 'h2', 'display' => 'open', 'show' => '', 'class' => '', ); } /** * Normalize frame atts (whitelists — junk falls back to the default). * * @return array{heading:string, heading_tag:string, display:string, show:int, class:string} */ public static function opts( array $a ) { $a = wp_parse_args( $a, self::defaults() ); $tag = strtolower( trim( (string) $a['heading_tag'] ) ); $dis = strtolower( trim( (string) $a['display'] ) ); return array( 'heading' => trim( wp_strip_all_tags( (string) $a['heading'] ) ), 'heading_tag' => in_array( $tag, self::TAGS, true ) ? $tag : 'h2', 'display' => in_array( $dis, self::DISPLAYS, true ) ? $dis : 'open', 'show' => is_numeric( $a['show'] ) ? max( 0, min( 500, (int) $a['show'] ) ) : 0, 'class' => self::clean_classes( $a['class'] ), ); } /** "a b c" → sanitized, de-duplicated class list ('' when empty). */ public static function clean_classes( $raw ) { $out = array(); foreach ( preg_split( '/\s+/', is_scalar( $raw ) ? (string) $raw : '' ) as $c ) { $c = sanitize_html_class( $c ); if ( '' !== $c ) { $out[ $c ] = $c; } } return implode( ' ', $out ); } /** Heading element ('' when no text). tag none → '' (or a when $force — collapsible summary). */ public static function heading( $text, $tag, $class = 'aoo-sc-title', $force = false ) { $text = (string) $text; if ( '' === $text ) { return ''; } if ( 'none' === $tag || ! in_array( $tag, self::TAGS, true ) ) { return $force ? '' . esc_html( $text ) . '' : ''; } return '<' . $tag . ' class="' . esc_attr( $class ) . '">' . esc_html( $text ) . ''; } /** * Wrap a widget body. * * @param string $inner Escaped HTML. * @param array $o opts() + { * tag root element for the open display: div | nav | section (default div), * base widget classes, e.g. 'aoo-sc aoo-sc-collections', * attrs escaped attribute string for the root (data-*), * body_attrs escaped attribute string that belongs to the landmark (aria-label) — root when open, body when collapsible, * wrapper block wrapper attributes (get_block_wrapper_attributes) — replaces class="base class" on the root, * heading_class class of the heading (default aoo-sc-title), * label summary text of a collapsible frame without heading, * }. */ public static function wrap( $inner, array $o ) { $f = self::opts( $o ); $tag = isset( $o['tag'] ) && in_array( $o['tag'], array( 'div', 'nav', 'section' ), true ) ? $o['tag'] : 'div'; $base = isset( $o['base'] ) ? (string) $o['base'] : 'aoo-sc'; $attrs = isset( $o['attrs'] ) ? (string) $o['attrs'] : ''; $body_at = isset( $o['body_attrs'] ) ? (string) $o['body_attrs'] : ''; $wrapper = isset( $o['wrapper'] ) ? trim( (string) $o['wrapper'] ) : ''; $hclass = isset( $o['heading_class'] ) ? (string) $o['heading_class'] : 'aoo-sc-title'; $label = isset( $o['label'] ) ? (string) $o['label'] : ''; if ( 'open' === $f['display'] ) { $root = '' !== $wrapper ? ' ' . self::add_class( $wrapper, $f['class'] ) : ' class="' . esc_attr( trim( $base . ' ' . $f['class'] ) ) . '"'; return '<' . $tag . $root . $body_at . $attrs . '>' . self::heading( $f['heading'], $f['heading_tag'], $hclass ) . $inner . ''; } $text = '' !== $f['heading'] ? $f['heading'] : $label; $root = '' !== $wrapper ? ' ' . self::add_class( $wrapper, 'aoo-w-collapsible ' . $f['class'] ) : ' class="' . esc_attr( trim( $base . ' aoo-w-collapsible ' . $f['class'] ) ) . '"'; return '' . '' . self::heading( $text, $f['heading_tag'], $hclass, true ) . '' . '<' . $tag . ' class="aoo-w-body"' . $body_at . '>' . $inner . '' . '
      '; } /** Add classes to an existing attribute string's class="…" (block wrapper). */ private static function add_class( $attrs, $classes ) { $classes = trim( preg_replace( '/\s+/', ' ', (string) $classes ) ); if ( '' === $classes ) { return $attrs; } if ( preg_match( '/\bclass="([^"]*)"/', $attrs ) ) { return preg_replace( '/\bclass="([^"]*)"/', 'class="$1 ' . esc_attr( $classes ) . '"', $attrs, 1 ); } return 'class="' . esc_attr( $classes ) . '" ' . $attrs; } /** *