Dashboard
PHP:
8.4.22
OS:
Linux
User:
provencez
/
/
home
/
provencez
/
www
/
wp-content
/
plugins
/
flexa-block
/
build
/
blocks
/
breadcrumb
📤 Upload
📝 New File
📁 New Folder
Close
Editing: render.php
<?php /** * Breadcrumb block — server-side render. * * CSS is generated at save time by Breadcrumb_CSS and printed inline on the front * end. This file outputs the trail markup: an <ol> of crumbs separated by the * chosen glyph, where the last crumb is the current page. In Automatic mode the * trail is built from the current page/post context (Home → ancestors → current); * in Manual mode it uses the hand-listed items. When enabled, a BreadcrumbList * JSON-LD block is printed once for rich results. Text inherits the theme's * typography unless the user overrode it. * * @package Flexa\Block * * @var array $attributes Block attributes. * @var string $content Save content (unused — dynamic block). * @var WP_Block $block Block instance. */ if ( ! defined( 'ABSPATH' ) ) { exit; } // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- $attributes provided by WP block API. use Flexa\Block\HTML_Helpers; $block_id = $attributes['blockId'] ?? ''; $anchor = $attributes['anchor'] ?? ''; $html_tag = HTML_Helpers::get_html_tag( $attributes, 'nav' ); $source = 'manual' === ( $attributes['source'] ?? 'auto' ) ? 'manual' : 'auto'; $home_text = (string) ( $attributes['homeText'] ?? '' ); $home_text = '' !== $home_text ? $home_text : __( 'Home', 'flexa-block' ); $home_icon = ! empty( $attributes['homeIcon'] ); $show_current = false !== ( $attributes['showCurrent'] ?? true ); $current_link = ! empty( $attributes['currentIsLink'] ); $enable_schema = ! empty( $attributes['enableSchema'] ); /** * The literal glyph printed between crumbs for the chosen separator token. * * @param array $separator Separator attribute { type, custom }. * @return string */ $separator_char = static function ( $separator ) { $type = is_array( $separator ) ? ( $separator['type'] ?? 'slash' ) : 'slash'; switch ( $type ) { case 'chevron': return '›'; case 'raquo': return '»'; case 'dash': return '-'; case 'custom': $custom = is_array( $separator ) ? (string) ( $separator['custom'] ?? '' ) : ''; return '' !== $custom ? $custom : '/'; default: return '/'; } }; /** * Build the automatic trail from the current query context. Each entry is * [ 'label' => string, 'url' => string ]; the last entry is the current page. * Falls back to a small sample trail when there is no page context (e.g. the * block is rendered outside the main query / in a REST preview). * * @param string $home_text Label for the leading Home crumb. * @return array */ $build_auto_trail = static function ( $home_text ) { $trail = [ [ 'label' => $home_text, 'url' => home_url( '/' ) ] ]; if ( is_front_page() ) { return [ [ 'label' => $home_text, 'url' => '' ] ]; } if ( is_singular() ) { $post_id = get_queried_object_id(); $post_type = get_post_type( $post_id ); // A custom post type: link its archive first (if it has one). if ( $post_type && 'post' !== $post_type && 'page' !== $post_type ) { $pt_obj = get_post_type_object( $post_type ); if ( $pt_obj && ! empty( $pt_obj->has_archive ) ) { $archive = get_post_type_archive_link( $post_type ); if ( $archive ) { $trail[] = [ 'label' => $pt_obj->labels->name ?? $post_type, 'url' => $archive ]; } } } // Page/post ancestors, from the top down. $ancestors = array_reverse( (array) get_post_ancestors( $post_id ) ); foreach ( $ancestors as $ancestor_id ) { $trail[] = [ 'label' => get_the_title( $ancestor_id ), 'url' => (string) get_permalink( $ancestor_id ) ]; } $trail[] = [ 'label' => get_the_title( $post_id ), 'url' => (string) get_permalink( $post_id ) ]; return $trail; } if ( is_category() || is_tag() || is_tax() ) { $term = get_queried_object(); if ( $term instanceof \WP_Term ) { $ancestors = array_reverse( (array) get_ancestors( $term->term_id, $term->taxonomy, 'taxonomy' ) ); foreach ( $ancestors as $ancestor_id ) { $parent = get_term( $ancestor_id, $term->taxonomy ); if ( $parent instanceof \WP_Term ) { $trail[] = [ 'label' => $parent->name, 'url' => (string) get_term_link( $parent ) ]; } } $trail[] = [ 'label' => $term->name, 'url' => (string) get_term_link( $term ) ]; return $trail; } } if ( is_post_type_archive() ) { $trail[] = [ 'label' => post_type_archive_title( '', false ), 'url' => '' ]; return $trail; } if ( is_author() ) { $trail[] = [ 'label' => (string) get_the_author_meta( 'display_name', (int) get_queried_object_id() ), 'url' => '' ]; return $trail; } if ( is_search() ) { /* translators: %s: search query. */ $trail[] = [ 'label' => sprintf( __( 'Search: %s', 'flexa-block' ), get_search_query() ), 'url' => '' ]; return $trail; } if ( is_404() ) { $trail[] = [ 'label' => __( 'Not found', 'flexa-block' ), 'url' => '' ]; return $trail; } // No usable context (e.g. editor/REST preview) → a representative sample. if ( count( $trail ) < 2 ) { $trail[] = [ 'label' => __( 'Category', 'flexa-block' ), 'url' => home_url( '/' ) ]; $trail[] = [ 'label' => __( 'Current page', 'flexa-block' ), 'url' => '' ]; } return $trail; }; // --- Build the trail. --- if ( 'manual' === $source ) { $items = $attributes['items'] ?? []; $trail = []; if ( is_array( $items ) ) { foreach ( $items as $item ) { if ( ! is_array( $item ) ) { continue; } $label = (string) ( $item['label'] ?? '' ); if ( '' === trim( $label ) ) { continue; } $trail[] = [ 'label' => $label, 'url' => (string) ( $item['url'] ?? '' ) ]; } } } else { $trail = $build_auto_trail( $home_text ); } $trail = array_values( $trail ); if ( empty( $trail ) ) { return; } // Drop the current (last) crumb when the user hid it. $last_index = count( $trail ) - 1; $visible = $show_current ? $trail : array_slice( $trail, 0, $last_index ); if ( empty( $visible ) ) { return; } $sep_glyph = $separator_char( $attributes['separator'] ?? [] ); // A house glyph used when the home icon is on but no custom icon was chosen. $default_house = '<svg class="flexa-icon" viewBox="0 0 24 24" width="1em" height="1em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 11l9-7 9 7"/><path d="M5 10v10h14V10"/></svg>'; // Resolve the home-icon markup once (safe: svg_kses'd or an <img> with esc_url). $home_icon_html = ''; if ( $home_icon ) { $icon = $attributes['homeIconValue'] ?? []; $markup = is_array( $icon ) ? (string) ( $icon['markup'] ?? '' ) : ''; $url = is_array( $icon ) ? (string) ( $icon['url'] ?? '' ) : ''; if ( '' !== $markup ) { $svg = HTML_Helpers::svg_kses( $markup ); $inner = '' !== $svg ? $svg : $default_house; $home_icon_html = '<span class="flexa-breadcrumb__home-icon">' . $inner . '</span>'; } elseif ( '' !== $url ) { $home_icon_html = '<img class="flexa-breadcrumb__home-icon" src="' . esc_url( $url ) . '" alt="" />'; } else { $home_icon_html = '<span class="flexa-breadcrumb__home-icon">' . $default_house . '</span>'; } } // --- Build the list markup. --- $sep_html = '<span class="flexa-breadcrumb__separator" aria-hidden="true">' . esc_html( $sep_glyph ) . '</span>'; $items_html = ''; foreach ( $visible as $i => $crumb ) { $is_current = $i === $last_index; $label = esc_html( (string) $crumb['label'] ); $url = (string) ( $crumb['url'] ?? '' ); $icon_html = 0 === $i ? $home_icon_html : ''; if ( $is_current ) { if ( $current_link && '' !== $url ) { $crumb_html = '<a class="flexa-breadcrumb__current" href="' . esc_url( $url ) . '" aria-current="page">' . $icon_html . $label . '</a>'; } else { $crumb_html = '<span class="flexa-breadcrumb__current" aria-current="page">' . $icon_html . $label . '</span>'; } } elseif ( '' !== $url ) { $crumb_html = '<a class="flexa-breadcrumb__link" href="' . esc_url( $url ) . '">' . $icon_html . $label . '</a>'; } else { $crumb_html = '<span class="flexa-breadcrumb__link">' . $icon_html . $label . '</span>'; } $show_sep = $i < count( $visible ) - 1; $item_class = 'flexa-breadcrumb__item' . ( $is_current ? ' flexa-breadcrumb__item--current' : '' ); $items_html .= '<li class="' . esc_attr( $item_class ) . '">' . $crumb_html . ( $show_sep ? $sep_html : '' ) . '</li>'; } // --- Optional BreadcrumbList schema (built from the FULL trail, printed once). --- $schema_html = ''; if ( $enable_schema ) { $elements = []; foreach ( $trail as $position => $crumb ) { $name = trim( wp_strip_all_tags( (string) $crumb['label'] ) ); if ( '' === $name ) { continue; } $element = [ '@type' => 'ListItem', 'position' => $position + 1, 'name' => $name, ]; $url = (string) ( $crumb['url'] ?? '' ); if ( '' !== $url ) { $element['item'] = esc_url_raw( $url ); } $elements[] = $element; } if ( ! empty( $elements ) ) { $schema = [ '@context' => 'https://schema.org', '@type' => 'BreadcrumbList', 'itemListElement' => $elements, ]; $json = wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); if ( false !== $json ) { $schema_html = '<script type="application/ld+json">' . $json . '</script>'; } } } // --- Wrapper classes + attributes. --- $classes = [ 'flexa-breadcrumb' ]; if ( '' !== $block_id ) { $classes[] = 'flexa-breadcrumb-' . sanitize_html_class( $block_id ); } $classes = HTML_Helpers::build_wrapper_classes( $classes, $attributes ); $wrapper_args = [ 'class' => implode( ' ', $classes ), 'aria-label' => __( 'Breadcrumb', 'flexa-block' ), ]; if ( $anchor ) { $wrapper_args['id'] = sanitize_html_class( $anchor ); } $wrapper_attributes = get_block_wrapper_attributes( $wrapper_args ); $data_attrs = HTML_Helpers::build_data_attrs( $attributes ); // Lazy background marker. $background = $attributes['background'] ?? []; $is_lazy_bg = ! empty( $background['lazyLoad'] ) && 'image' === ( $background['type'] ?? 'none' ) && '' !== ( $background['image']['url'] ?? '' ); $lazy_marker = $is_lazy_bg ? ' data-flexa-lazy-bg' : ''; printf( '<%1$s %2$s%3$s%4$s>%5$s<ol class="flexa-breadcrumb__list">%6$s</ol></%1$s>', esc_html( $html_tag ), $wrapper_attributes, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- built via get_block_wrapper_attributes. $data_attrs, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- keys sanitized, values escaped in helper. $lazy_marker, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal. $schema_html, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- wp_json_encode output, script tag static. $items_html // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- labels esc_html'd, urls esc_url'd, icon svg_kses'd above. );
Save
Cancel