chore: complete M1.1 runtime QA and release packaging
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/**
|
||||
* Breadcrumbs — semantic, RTL/LTR safe, Woo-aware, SEO-friendly.
|
||||
*
|
||||
* Data: array of ['label'=>string,'url'=>string|null,'current'=>bool]
|
||||
* If $args['items'] not provided, auto-builds from WP/WC context.
|
||||
*
|
||||
* @package XShop
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$args = wp_parse_args($args ?? [], ['items' => null]);
|
||||
$items = $args['items'];
|
||||
|
||||
if ($items === null) {
|
||||
$items = [];
|
||||
// Home.
|
||||
$items[] = ['label' => esc_html__('Home', 'xshop'), 'url' => home_url('/'), 'current' => false];
|
||||
|
||||
if (is_front_page()) {
|
||||
// Front page is current; keep only home as current.
|
||||
$items[0]['current'] = true;
|
||||
$items[0]['url'] = null;
|
||||
} elseif (function_exists('is_woocommerce') && xshop_has_woocommerce() && (is_woocommerce() || is_cart() || is_checkout() || is_account_page())) {
|
||||
// Delegate to Woo breadcrumb if available, but provide fallback.
|
||||
if (function_exists('is_shop') && is_shop()) {
|
||||
$items[] = ['label' => esc_html__('Shop', 'xshop'), 'url' => null, 'current' => true];
|
||||
} elseif (function_exists('is_product_category') && is_product_category()) {
|
||||
$shopUrl = function_exists('wc_get_page_permalink') ? wc_get_page_permalink('shop') : home_url('/');
|
||||
$items[] = ['label' => esc_html__('Shop', 'xshop'), 'url' => $shopUrl, 'current' => false];
|
||||
$term = get_queried_object();
|
||||
if ($term instanceof WP_Term) {
|
||||
$items[] = ['label' => $term->name, 'url' => null, 'current' => true];
|
||||
}
|
||||
} elseif (function_exists('is_product') && is_product()) {
|
||||
$shopUrl = function_exists('wc_get_page_permalink') ? wc_get_page_permalink('shop') : home_url('/');
|
||||
$items[] = ['label' => esc_html__('Shop', 'xshop'), 'url' => $shopUrl, 'current' => false];
|
||||
$items[] = ['label' => get_the_title(), 'url' => null, 'current' => true];
|
||||
} elseif (function_exists('is_cart') && is_cart()) {
|
||||
$items[] = ['label' => esc_html__('Cart', 'xshop'), 'url' => null, 'current' => true];
|
||||
} elseif (function_exists('is_checkout') && is_checkout()) {
|
||||
$items[] = ['label' => esc_html__('Checkout', 'xshop'), 'url' => null, 'current' => true];
|
||||
} elseif (function_exists('is_account_page') && is_account_page()) {
|
||||
$items[] = ['label' => esc_html__('My Account', 'xshop'), 'url' => null, 'current' => true];
|
||||
}
|
||||
} elseif (is_home()) {
|
||||
$postsPage = get_option('page_for_posts');
|
||||
$label = $postsPage ? get_the_title((int) $postsPage) : esc_html__('Blog', 'xshop');
|
||||
$items[] = ['label' => $label, 'url' => null, 'current' => true];
|
||||
} elseif (is_category() || is_tag() || is_tax()) {
|
||||
$term = get_queried_object();
|
||||
if ($term instanceof WP_Term) {
|
||||
$items[] = ['label' => $term->name, 'url' => null, 'current' => true];
|
||||
}
|
||||
} elseif (is_search()) {
|
||||
$items[] = ['label' => sprintf(esc_html__('Search: %s', 'xshop'), get_search_query()), 'url' => null, 'current' => true];
|
||||
} elseif (is_404()) {
|
||||
$items[] = ['label' => esc_html__('Not Found', 'xshop'), 'url' => null, 'current' => true];
|
||||
} elseif (is_singular()) {
|
||||
$postType = get_post_type();
|
||||
if ($postType && $postType !== 'post' && $postType !== 'page') {
|
||||
$obj = get_post_type_object($postType);
|
||||
if ($obj) {
|
||||
$items[] = ['label' => $obj->labels->name, 'url' => null, 'current' => false];
|
||||
}
|
||||
} elseif ($postType === 'post') {
|
||||
$cat = get_the_category();
|
||||
if (!empty($cat[0])) {
|
||||
$items[] = ['label' => $cat[0]->name, 'url' => get_category_link($cat[0]->term_id), 'current' => false];
|
||||
}
|
||||
}
|
||||
$items[] = ['label' => get_the_title(), 'url' => null, 'current' => true];
|
||||
} elseif (is_archive()) {
|
||||
$items[] = ['label' => get_the_archive_title(), 'url' => null, 'current' => true];
|
||||
}
|
||||
|
||||
// Mark last as current if none marked.
|
||||
$hasCurrent = false;
|
||||
foreach ($items as $it) { if (!empty($it['current'])) { $hasCurrent = true; break; } }
|
||||
if (!$hasCurrent && count($items) > 0) {
|
||||
$items[count($items) - 1]['current'] = true;
|
||||
$items[count($items) - 1]['url'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Never break if empty.
|
||||
if (empty($items)) { return; }
|
||||
|
||||
// Allow SEO plugins / child themes to filter.
|
||||
$items = apply_filters('xshop_breadcrumbs_items', $items);
|
||||
if (empty($items) || !is_array($items)) { return; }
|
||||
?>
|
||||
<nav class="xshop-breadcrumbs" aria-label="<?php esc_attr_e('Breadcrumb', 'xshop'); ?>">
|
||||
<ol>
|
||||
<?php foreach ($items as $item):
|
||||
$label = isset($item['label']) ? (string) $item['label'] : '';
|
||||
if ($label === '') { continue; }
|
||||
$isCurrent = !empty($item['current']);
|
||||
$url = isset($item['url']) ? (string) $item['url'] : '';
|
||||
?>
|
||||
<li>
|
||||
<?php if ($isCurrent || $url === ''): ?>
|
||||
<span aria-current="page"><?php echo esc_html($label); ?></span>
|
||||
<?php else: ?>
|
||||
<a href="<?php echo esc_url($url); ?>"><?php echo esc_html($label); ?></a>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ol>
|
||||
</nav>
|
||||
Reference in New Issue
Block a user