124 lines
4.6 KiB
PHP
124 lines
4.6 KiB
PHP
<?php
|
|
/**
|
|
* XShop Product Card — reusable for shop/category/home/related/upsells/search.
|
|
*
|
|
* Expects: $args['product'] = WC_Product|int (ID)
|
|
* Optional: $args['show_hooks'] bool (wishlist/compare placeholders)
|
|
*
|
|
* @package XShop
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
$product = $args['product'] ?? null;
|
|
if (is_int($product)) {
|
|
$product = wc_get_product($product);
|
|
}
|
|
if (!$product instanceof WC_Product) {
|
|
global $product;
|
|
if (!isset($product) || !$product instanceof WC_Product) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
$pid = $product->get_id();
|
|
$title = $product->get_name();
|
|
if ($title === '') {
|
|
$title = esc_html__('Untitled', 'xshop');
|
|
}
|
|
$permalink = get_permalink($pid);
|
|
$priceHtml = $product->get_price_html();
|
|
$rating = $product->get_average_rating();
|
|
$count = $product->get_rating_count();
|
|
$stock = $product->get_stock_status();
|
|
$isOnSale = $product->is_on_sale();
|
|
$featured = $product->is_featured();
|
|
$type = $product->get_type();
|
|
$showHooks = !empty($args['show_hooks']);
|
|
?>
|
|
<article <?php wc_product_class('xshop-product-card', $product); ?>>
|
|
<a href="<?php echo esc_url($permalink); ?>" class="xshop-product-card__media" aria-label="<?php echo esc_attr($title); ?>">
|
|
<?php
|
|
$imageId = $product->get_image_id();
|
|
if ($imageId) {
|
|
echo wp_get_attachment_image($imageId, 'xshop-card', false, ['loading' => 'lazy', 'decoding' => 'async', 'alt' => esc_attr($title)]);
|
|
} elseif (has_post_thumbnail($pid)) {
|
|
echo get_the_post_thumbnail($pid, 'xshop-card', ['loading' => 'lazy', 'decoding' => 'async', 'alt' => esc_attr($title)]);
|
|
} else {
|
|
echo '<span class="xshop-card__media--placeholder" style="display:flex;inline-size:100%;block-size:100%;align-items:center;justify-content:center;">' . esc_html__('No image', 'xshop') . '</span>';
|
|
}
|
|
?>
|
|
<span class="xshop-product-card__badges" aria-hidden="true">
|
|
<?php if ($isOnSale): ?>
|
|
<span class="xshop-badge xshop-badge--sale">
|
|
<?php
|
|
if ($product->is_type('variable')) {
|
|
esc_html_e('Sale', 'xshop');
|
|
} else {
|
|
$regular = (float) $product->get_regular_price();
|
|
$sale = (float) $product->get_sale_price();
|
|
if ($regular > 0 && $sale > 0) {
|
|
$pct = (int) round(100 - ($sale / $regular * 100));
|
|
echo esc_html(sprintf('-%d%%', $pct));
|
|
} else {
|
|
esc_html_e('Sale', 'xshop');
|
|
}
|
|
}
|
|
?>
|
|
</span>
|
|
<?php endif; ?>
|
|
<?php if ($stock === 'outofstock'): ?>
|
|
<span class="xshop-badge xshop-badge--outofstock"><?php esc_html_e('Out of stock', 'xshop'); ?></span>
|
|
<?php endif; ?>
|
|
<?php if ($featured): ?>
|
|
<span class="xshop-badge xshop-badge--featured"><?php esc_html_e('Featured', 'xshop'); ?></span>
|
|
<?php endif; ?>
|
|
</span>
|
|
</a>
|
|
|
|
<div class="xshop-product-card__body">
|
|
<h3 class="xshop-product-card__title">
|
|
<a href="<?php echo esc_url($permalink); ?>"><?php echo esc_html($title); ?></a>
|
|
</h3>
|
|
|
|
<?php if ($priceHtml !== ''): ?>
|
|
<div class="xshop-product-card__price"><?php echo wp_kses_post($priceHtml); ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="xshop-product-card__meta">
|
|
<?php if ($rating > 0): ?>
|
|
<span class="xshop-product-card__rating" aria-label="<?php echo esc_attr(sprintf(esc_html__('Rated %s out of 5', 'xshop'), $rating)); ?>">
|
|
<?php
|
|
$stars = str_repeat('★', (int) round($rating)) . str_repeat('☆', 5 - (int) round($rating));
|
|
echo esc_html($stars) . ' <span style="color:var(--xshop-muted)">(' . esc_html((string) $count) . ')</span>';
|
|
?>
|
|
</span>
|
|
<?php endif; ?>
|
|
<?php if ($type === 'variable'): ?>
|
|
<span><?php esc_html_e('Variable', 'xshop'); ?></span>
|
|
<?php endif; ?>
|
|
<?php if ($stock === 'outofstock'): ?>
|
|
<span><?php esc_html_e('Out of stock', 'xshop'); ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="xshop-product-card__actions">
|
|
<?php
|
|
// Use Woo's add-to-cart template (handles simple/variable correctly)
|
|
woocommerce_template_loop_add_to_cart();
|
|
?>
|
|
<?php if ($showHooks): ?>
|
|
<span class="xshop-product-card__hook" aria-hidden="true"><?php esc_html_e('Wishlist', 'xshop'); ?></span>
|
|
<span class="xshop-product-card__hook" aria-hidden="true"><?php esc_html_e('Compare', 'xshop'); ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php
|
|
// Hook placeholders for future wishlist/compare (no fake functionality)
|
|
do_action('xshop_product_card_after_actions', $product);
|
|
?>
|
|
</div>
|
|
</article>
|