'rooster-lms-dock rooster-lms-dock--' . $mode . ' rooster-lms-dock--' . $side, 'data-rl-dock' => sanitize_key( $key ), 'data-rl-dock-mode' => $mode, 'data-rl-dock-side' => $side, 'data-rl-dock-layout' => $layout, ); } public static function layout( string $key ): string { $name = 'rooster_lms_dock_' . sanitize_key( $key ); $layout = isset( $_COOKIE[ $name ] ) ? sanitize_key( wp_unslash( $_COOKIE[ $name ] ) ) : ''; return in_array( $layout, array( self::FLOATING, self::LEFT, self::RIGHT ), true ) ? $layout : self::RIGHT; } public static function at( string $key ): array { $name = 'rooster_lms_dock_' . sanitize_key( $key ) . '_at'; $value = isset( $_COOKIE[ $name ] ) ? sanitize_text_field( wp_unslash( $_COOKIE[ $name ] ) ) : ''; if ( 1 !== preg_match( '/^(\d{1,5})?\.(\d{1,5})?\.([01])(?:\.(\d{3,4})\.(\d{2,4}))?$/', $value, $m ) ) { return array( 'x' => null, 'y' => null, 'folded' => false, 'w' => null, 'h' => null, ); } $placed = '' !== $m[1] && '' !== $m[2]; return array( 'x' => $placed ? (int) $m[1] : null, 'y' => $placed ? (int) $m[2] : null, 'folded' => '1' === $m[3], 'w' => isset( $m[4] ) && '' !== $m[4] ? (int) $m[4] : null, 'h' => isset( $m[5] ) && '' !== $m[5] ? (int) $m[5] : null, ); } public static function panel_attributes( string $key, string $classes ): string { $state = self::panel_state( $key ); return 'class="' . esc_attr( trim( $classes . ' ' . implode( ' ', $state['classes'] ) ) ) . '" data-rl-dock-panel' . ( '' !== $state['style'] ? ' style="' . esc_attr( $state['style'] ) . '"' : '' ); } public static function panel_state( string $key ): array { $classes = array( 'rooster-lms-dock__panel' ); $style = ''; $folded = false; if ( self::FLOATING === self::layout( $key ) ) { $at = self::at( $key ); if ( null !== $at['x'] ) { $classes[] = 'is-pinned'; $style = 'left:' . (int) $at['x'] . 'px;top:' . (int) $at['y'] . 'px'; } if ( $at['folded'] ) { $classes[] = 'is-folded'; $folded = true; } if ( null !== $at['w'] && null !== $at['h'] ) { $style .= ( '' !== $style ? ';' : '' ) . 'width:' . (int) $at['w'] . 'px' . ( $folded ? '' : ';height:' . (int) $at['h'] . 'px' ); } } return array( 'classes' => $classes, 'style' => $style, 'folded' => $folded, ); } public static function head( string $title, string $layout = self::FLOATING, bool $folded = false ): string { $icon = static fn( string $path ): string => ''; $button = static fn( string $attr, string $label, string $path, string $extra = '' ): string => ''; $layouts = array( self::FLOATING => array( __( 'Float over the page (full-width content)', 'rooster-lms' ), 'M3 4h18v16H3zM13 7h5v6h-5' ), self::LEFT => array( __( 'Dock on the left', 'rooster-lms' ), 'M3 4h18v16H3zM9 4v16' ), self::RIGHT => array( __( 'Dock on the right', 'rooster-lms' ), 'M3 4h18v16H3zM15 4v16' ), ); $themed = function_exists( 'rooster_icon' ) && Theme::declares( 'C11' ); if ( $themed ) { $layouts = array( self::LEFT => array( __( 'Dock at the start', 'rooster-lms' ), 'panel-left' ), self::RIGHT => array( __( 'Dock at the end', 'rooster-lms' ), 'panel-right' ), self::FLOATING => array( __( 'Undock (drag to move, drag the corner to resize)', 'rooster-lms' ), 'panel-float' ), ); $icon = static fn( string $slug ): string => (string) rooster_icon( $slug, array( 'width' => 18, 'height' => 18, ) ); $button = static fn( string $attr, string $label, string $slug, string $extra = '' ): string => ''; } $html = '