Compare commits
No commits in common. '8e354cb7296663ab4d2395c61f97ff894080f335' and '377cabf3cce49de1b33e96a71646451571208017' have entirely different histories.
8e354cb729
...
377cabf3cc
@ -1,380 +0,0 @@ |
|||||||
<? |
|
||||||
|
|
||||||
/** |
|
||||||
* Добавление событий контрибуции для FP Pixel |
|
||||||
* только на боевом сайте АЕ |
|
||||||
*/ |
|
||||||
if ($site_env->site_mode == 'production' && $site_env->site_region == 'ae') { |
|
||||||
|
|
||||||
// Проверка на тестовый режим для метрик |
|
||||||
// TO_DO: дуюлирует логику is_gp_test_mode в wp-content/themes/cosmopet/global-functions/multisite-functions.php |
|
||||||
function is_gp_test_mode() |
|
||||||
{ |
|
||||||
if (isset($_GET['gp-test']) && $_GET['gp-test'] == '1') { |
|
||||||
return true; |
|
||||||
} |
|
||||||
if (is_user_logged_in() && current_user_can('administrator')) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
add_action('wp_footer', 'add_facebook_pixel_events'); |
|
||||||
function add_facebook_pixel_events() |
|
||||||
{ |
|
||||||
if (is_gp_test_mode()) |
|
||||||
return; |
|
||||||
|
|
||||||
global $product; |
|
||||||
|
|
||||||
// 1. ViewContent |
|
||||||
if (is_product() && $product && $product->get_price() > 0) { |
|
||||||
?> |
|
||||||
<script> |
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
|
||||||
fbq('track', 'ViewContent', { |
|
||||||
content_ids: ['<?php echo $product->get_id(); ?>'],
|
|
||||||
content_type: 'product', |
|
||||||
value: <?php echo $product->get_price(); ?>,
|
|
||||||
currency: '<?php echo get_woocommerce_currency(); ?>'
|
|
||||||
}); |
|
||||||
}); |
|
||||||
</script> |
|
||||||
<?php |
|
||||||
} |
|
||||||
|
|
||||||
// 2. InitiateCheckout |
|
||||||
if (is_checkout() && !is_wc_endpoint_url('order-received') && WC()->cart && WC()->cart->get_cart_contents_count() > 0) { |
|
||||||
?> |
|
||||||
<script> |
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
|
||||||
fbq('track', 'InitiateCheckout'); |
|
||||||
}); |
|
||||||
</script> |
|
||||||
<?php |
|
||||||
} |
|
||||||
|
|
||||||
// 3. AddToCart |
|
||||||
if (is_product() || is_shop() || is_cart()) { |
|
||||||
?> |
|
||||||
<script> |
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
|
||||||
jQuery(function($) { |
|
||||||
$(document.body).on('added_to_cart', function(event, fragments, cart_hash, $button) { |
|
||||||
var productId = $button.data('product_id') || ''; |
|
||||||
var quantity = $button.data('quantity') || 1; |
|
||||||
var productName = $button.data('product_sku') || |
|
||||||
$button.closest('.product').find('.woocommerce-loop-product__title').text().trim() || 'Unknown'; |
|
||||||
var priceElement = $button.closest('.product').find('.price .amount').text().replace(/[^0-9.]/g, '') || '0.00'; |
|
||||||
var currency = '<?php echo get_woocommerce_currency(); ?>';
|
|
||||||
|
|
||||||
fbq('track', 'AddToCart', { |
|
||||||
content_ids: [productId], |
|
||||||
content_type: 'product', |
|
||||||
value: parseFloat(priceElement) * quantity, |
|
||||||
currency: currency |
|
||||||
}); |
|
||||||
|
|
||||||
window.dataLayer = window.dataLayer || []; |
|
||||||
window.dataLayer.push({ |
|
||||||
'event': 'add_to_cart', |
|
||||||
'ecommerce': { |
|
||||||
'currency': currency, |
|
||||||
'value': parseFloat(priceElement) * quantity, |
|
||||||
'items': [{ |
|
||||||
'item_id': productId, |
|
||||||
'item_name': productName, |
|
||||||
'price': parseFloat(priceElement), |
|
||||||
'quantity': quantity |
|
||||||
}] |
|
||||||
} |
|
||||||
}); |
|
||||||
}); |
|
||||||
}); |
|
||||||
}); |
|
||||||
</script> |
|
||||||
<?php |
|
||||||
} |
|
||||||
|
|
||||||
// 4. AddPaymentInfo |
|
||||||
if (is_checkout() && !is_wc_endpoint_url('order-received') && WC()->cart && WC()->cart->get_cart_contents_count() > 0) { |
|
||||||
$currency = get_woocommerce_currency(); |
|
||||||
$cart_total = WC()->cart->get_total('edit'); |
|
||||||
?> |
|
||||||
<script> |
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
|
||||||
fbq('track', 'AddPaymentInfo', { |
|
||||||
value: <?php echo $cart_total; ?>,
|
|
||||||
currency: '<?php echo $currency; ?>'
|
|
||||||
}); |
|
||||||
|
|
||||||
window.dataLayer = window.dataLayer || []; |
|
||||||
window.dataLayer.push({ |
|
||||||
'event': 'add_payment_info', |
|
||||||
'ecommerce': { |
|
||||||
'currency': '<?php echo $currency; ?>',
|
|
||||||
'value': <?php echo $cart_total; ?> |
|
||||||
} |
|
||||||
}); |
|
||||||
}); |
|
||||||
</script> |
|
||||||
<?php |
|
||||||
} |
|
||||||
|
|
||||||
// 5. Purchase |
|
||||||
if (is_wc_endpoint_url('order-received')) { |
|
||||||
$order_id = absint(get_query_var('order-received')); |
|
||||||
if (!$order_id) |
|
||||||
return; |
|
||||||
|
|
||||||
$order = wc_get_order($order_id); |
|
||||||
if (!$order || ($order->get_status() !== 'processing' && $order->get_status() !== 'completed')) |
|
||||||
return; |
|
||||||
|
|
||||||
$items = []; |
|
||||||
foreach ($order->get_items() as $item) { |
|
||||||
$product = $item->get_product(); |
|
||||||
$items[] = [ |
|
||||||
'item_id' => $product->get_id(), |
|
||||||
'item_name' => $product->get_name(), |
|
||||||
'price' => $product->get_price(), |
|
||||||
'quantity' => $item->get_quantity() |
|
||||||
]; |
|
||||||
} |
|
||||||
?> |
|
||||||
<script> |
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
|
||||||
fbq('track', 'Purchase', { |
|
||||||
value: <?php echo $order->get_total(); ?>,
|
|
||||||
currency: '<?php echo $order->get_currency(); ?>',
|
|
||||||
content_ids: [<?php echo implode(',', array_column($items, 'item_id')); ?>],
|
|
||||||
content_type: 'product' |
|
||||||
}); |
|
||||||
|
|
||||||
window.dataLayer = window.dataLayer || []; |
|
||||||
window.dataLayer.push({ |
|
||||||
'event': 'purchase', |
|
||||||
'ecommerce': { |
|
||||||
'currency': '<?php echo $order->get_currency(); ?>',
|
|
||||||
'value': <?php echo $order->get_total(); ?>,
|
|
||||||
'items': <?php echo json_encode($items); ?> |
|
||||||
} |
|
||||||
}); |
|
||||||
}); |
|
||||||
</script> |
|
||||||
<?php |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
add_action('woocommerce_thankyou', 'send_purchase_to_metrika'); |
|
||||||
function send_purchase_to_metrika($order_id) |
|
||||||
{ |
|
||||||
if (is_gp_test_mode()) |
|
||||||
return; |
|
||||||
|
|
||||||
if (!$order_id) |
|
||||||
return; |
|
||||||
|
|
||||||
$order = wc_get_order($order_id); |
|
||||||
if ($order->get_status() !== 'processing' && $order->get_status() !== 'completed') |
|
||||||
return; |
|
||||||
|
|
||||||
$items = []; |
|
||||||
foreach ($order->get_items() as $item) { |
|
||||||
$product = $item->get_product(); |
|
||||||
$items[] = [ |
|
||||||
'id' => $product->get_id(), |
|
||||||
'name' => $product->get_name(), |
|
||||||
'price' => $product->get_price(), |
|
||||||
'quantity' => $item->get_quantity() |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
$currency = $order->get_currency(); |
|
||||||
?> |
|
||||||
<script> |
|
||||||
window.dataLayer = window.dataLayer || []; |
|
||||||
dataLayer.push({ |
|
||||||
'ecommerce': { |
|
||||||
'purchase': { |
|
||||||
'actionField': { |
|
||||||
'id': '<?php echo $order_id; ?>',
|
|
||||||
'revenue': '<?php echo $order->get_total(); ?>',
|
|
||||||
'currency': '<?php echo $currency; ?>'
|
|
||||||
}, |
|
||||||
'products': <?php echo json_encode($items); ?> |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
yaCounter96481053.reachGoal('purchase', { |
|
||||||
'order_id': '<?php echo $order_id; ?>',
|
|
||||||
'order_price': '<?php echo $order->get_total(); ?>',
|
|
||||||
'currency': '<?php echo $currency; ?>',
|
|
||||||
'items': <?php echo json_encode($items); ?> |
|
||||||
}); |
|
||||||
|
|
||||||
fbq('track', 'Purchase', { |
|
||||||
value: <?php echo $order->get_total(); ?>,
|
|
||||||
currency: '<?php echo $currency; ?>',
|
|
||||||
content_ids: [<?php echo implode(',', array_column($items, 'id')); ?>],
|
|
||||||
content_type: 'product' |
|
||||||
}); |
|
||||||
</script> |
|
||||||
<?php |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// Функция событий Meta Pixel |
|
||||||
|
|
||||||
add_action('wp_head', function () { |
|
||||||
global $site_env; |
|
||||||
$show_pixel = false; |
|
||||||
|
|
||||||
// Для продакшена |
|
||||||
if ($site_env->site_mode === 'production' && $site_env->site_region === 'ae') { |
|
||||||
$show_pixel = true; |
|
||||||
} |
|
||||||
|
|
||||||
// Для тестовых стендов AE |
|
||||||
if ($site_env->site_mode === 'develope' && $site_env->site_region === 'ae') { |
|
||||||
$show_pixel = true; |
|
||||||
} |
|
||||||
|
|
||||||
// Дополнительные проверки |
|
||||||
$skip_tracking = false; |
|
||||||
|
|
||||||
// Исключаем админов |
|
||||||
if (current_user_can('administrator')) { |
|
||||||
$skip_tracking = true; |
|
||||||
} |
|
||||||
|
|
||||||
// Исключаем gp-test режим |
|
||||||
if ($site_env->is_gp_test_mode) { |
|
||||||
$skip_tracking = true; |
|
||||||
} |
|
||||||
|
|
||||||
// Исключаем если есть параметр gp-test=1 в URL |
|
||||||
if (isset($_GET['gp-test']) && $_GET['gp-test'] == '1') { |
|
||||||
$skip_tracking = true; |
|
||||||
} |
|
||||||
|
|
||||||
if ($show_pixel && !$skip_tracking) { |
|
||||||
$context = [ |
|
||||||
'currency' => get_woocommerce_currency(), |
|
||||||
]; |
|
||||||
|
|
||||||
// Определяем тип страницы и подготавливаем данные |
|
||||||
if (is_product()) { |
|
||||||
// Страница товара - ViewContent |
|
||||||
global $product; |
|
||||||
if ($product && $product instanceof WC_Product) { |
|
||||||
$context['pixel_event_type'] = 'ViewContent'; |
|
||||||
$context['product'] = [ |
|
||||||
'id' => $product->get_id(), |
|
||||||
'name' => $product->get_name(), |
|
||||||
'price' => floatval($product->get_price()), |
|
||||||
'sku' => $product->get_sku(), |
|
||||||
'category' => wp_get_post_terms($product->get_id(), 'product_cat', ['fields' => 'names'])[0] ?? '', |
|
||||||
]; |
|
||||||
} |
|
||||||
} elseif (is_checkout() && !is_order_received_page()) { |
|
||||||
// Страница чекаута - InitiateCheckout |
|
||||||
$context['pixel_event_type'] = 'InitiateCheckout'; |
|
||||||
if (WC()->cart && !WC()->cart->is_empty()) { |
|
||||||
$context['cart_total'] = floatval(WC()->cart->get_total('edit')); |
|
||||||
$context['cart_items'] = []; |
|
||||||
$context['content_ids'] = []; |
|
||||||
|
|
||||||
foreach (WC()->cart->get_cart() as $cart_item) { |
|
||||||
$product = $cart_item['data']; |
|
||||||
if ($product && $product instanceof WC_Product) { |
|
||||||
$item_data = [ |
|
||||||
'item_id' => $product->get_id(), |
|
||||||
'item_name' => $product->get_name(), |
|
||||||
'price' => floatval($product->get_price()), |
|
||||||
'quantity' => intval($cart_item['quantity']), |
|
||||||
'category' => wp_get_post_terms($product->get_id(), 'product_cat', ['fields' => 'names'])[0] ?? '', |
|
||||||
]; |
|
||||||
$context['cart_items'][] = $item_data; |
|
||||||
$context['content_ids'][] = $product->get_id(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} elseif (is_order_received_page()) { |
|
||||||
// Страница благодарности - Purchase |
|
||||||
$order_id = get_query_var('order-received'); |
|
||||||
if ($order_id) { |
|
||||||
$order = wc_get_order($order_id); |
|
||||||
if ($order && $order instanceof WC_Order) { |
|
||||||
$context['pixel_event_type'] = 'Purchase'; |
|
||||||
$order_items = []; |
|
||||||
$content_ids = []; |
|
||||||
|
|
||||||
foreach ($order->get_items() as $item) { |
|
||||||
if ($item instanceof WC_Order_Item_Product) { |
|
||||||
$product = $item->get_product(); |
|
||||||
if ($product && $product instanceof WC_Product) { |
|
||||||
$order_items[] = [ |
|
||||||
'item_id' => $product->get_id(), |
|
||||||
'item_name' => $product->get_name(), |
|
||||||
'price' => floatval($item->get_total() / $item->get_quantity()), |
|
||||||
'quantity' => intval($item->get_quantity()), |
|
||||||
'category' => wp_get_post_terms($product->get_id(), 'product_cat', ['fields' => 'names'])[0] ?? '', |
|
||||||
]; |
|
||||||
$content_ids[] = $product->get_id(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
$context['order'] = [ |
|
||||||
'id' => $order->get_id(), |
|
||||||
'total' => floatval($order->get_total()), |
|
||||||
'currency' => $order->get_currency(), |
|
||||||
'items' => $order_items, |
|
||||||
'content_ids' => $content_ids, |
|
||||||
'order_key' => $order->get_order_key(), |
|
||||||
]; |
|
||||||
} |
|
||||||
} |
|
||||||
} else { |
|
||||||
// Все остальные страницы - PageView + подготовка для AddToCart |
|
||||||
$context['pixel_event_type'] = 'PageView'; |
|
||||||
$context['enable_addtocart'] = true; // Включаем обработчик AddToCart |
|
||||||
|
|
||||||
// Дополнительные данные для PageView |
|
||||||
global $wp_query; |
|
||||||
$context['page_data'] = [ |
|
||||||
'page_title' => wp_get_document_title(), |
|
||||||
'page_url' => home_url(add_query_arg(array(), $wp_query->request)), |
|
||||||
'page_type' => get_page_type(), |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
// Рендерим шаблон |
|
||||||
\Timber\Timber::render('templates/head-pixel-functions.twig', $context); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
|
|
||||||
function get_page_type() |
|
||||||
{ |
|
||||||
if (is_home() || is_front_page()) { |
|
||||||
return 'home'; |
|
||||||
} elseif (is_shop()) { |
|
||||||
return 'shop'; |
|
||||||
} elseif (is_product_category()) { |
|
||||||
return 'category'; |
|
||||||
} elseif (is_product_tag()) { |
|
||||||
return 'tag'; |
|
||||||
} elseif (is_search()) { |
|
||||||
return 'search'; |
|
||||||
} elseif (is_cart()) { |
|
||||||
return 'cart'; |
|
||||||
} elseif (is_account_page()) { |
|
||||||
return 'account'; |
|
||||||
} else { |
|
||||||
return 'other'; |
|
||||||
} |
|
||||||
} |
|
@ -1,18 +0,0 @@ |
|||||||
<? |
|
||||||
|
|
||||||
add_filter('wpseo_canonical', '__return_false'); |
|
||||||
add_filter('wpseo_opengraph_url', '__return_false'); |
|
||||||
add_filter('wpseo_add_x_default_hreflang', '__return_false'); |
|
||||||
add_filter('wpseo_disable_adjacent_rel_links', '__return_true'); |
|
||||||
|
|
||||||
/* Добавление canonical-ссылок */ |
|
||||||
add_action('wp_head', function () { |
|
||||||
if (!is_admin()) { |
|
||||||
static $canonical_added = false; |
|
||||||
if ($canonical_added) |
|
||||||
return; |
|
||||||
$canonical_added = true; |
|
||||||
$current_url = strtok(trailingslashit(home_url($_SERVER['REQUEST_URI'])), '?'); |
|
||||||
echo '<link rel="canonical" href="' . esc_url($current_url) . '" />' . "\n"; |
|
||||||
} |
|
||||||
}); |
|
@ -1,661 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
use Timber; |
|
||||||
use Timber\PostCollection; |
|
||||||
use Timber\Integrations\WooCommerce\Product as TimberProduct; |
|
||||||
|
|
||||||
class CosmopetProduct extends TimberProduct { |
|
||||||
|
|
||||||
protected $sibling_categories = [ |
|
||||||
'pa_compound', |
|
||||||
'pa_dog-size', |
|
||||||
'pa_reproductive-status', |
|
||||||
'pa_age-of-the-cat', |
|
||||||
'pa_age-of-the-dog', |
|
||||||
'pa_series', |
|
||||||
]; |
|
||||||
|
|
||||||
public function __construct ($pid = null) { |
|
||||||
parent::__construct($pid); |
|
||||||
} |
|
||||||
|
|
||||||
public function getComposition() { |
|
||||||
return get_post_meta($this->id, '_composition', true); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public function getImageGallery($size) { |
|
||||||
// Инициализируем массив для результатов |
|
||||||
$images_array = array(); |
|
||||||
|
|
||||||
// Получаем ID основного изображения товара |
|
||||||
$thumbnail_id = get_post_thumbnail_id($this->id); |
|
||||||
// Добавляем основное изображение |
|
||||||
if ($thumbnail_id) { |
|
||||||
$images_array[] = array( |
|
||||||
'url' => wp_get_attachment_image_url($thumbnail_id, $size), |
|
||||||
'alt' => get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true) |
|
||||||
); |
|
||||||
} else { |
|
||||||
// Используем заглушку, если нет основного изображения |
|
||||||
$images_array[] = array( |
|
||||||
'url' => wc_placeholder_img_src(), |
|
||||||
'alt' => __('Placeholder image', 'woocommerce') |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
// Получаем галерею изображений |
|
||||||
if ($this->product && method_exists($this->product, 'get_gallery_image_ids')) { |
|
||||||
$gallery_image_ids = $this->product->get_gallery_image_ids(); |
|
||||||
} else { |
|
||||||
$gallery_image_ids = []; |
|
||||||
} |
|
||||||
|
|
||||||
// Добавляем изображения из галереи |
|
||||||
if (!empty($gallery_image_ids)) { |
|
||||||
foreach ($gallery_image_ids as $image_id) { |
|
||||||
$image_url = wp_get_attachment_image_url($image_id, $size); |
|
||||||
if ($image_url) { |
|
||||||
$images_array[] = array( |
|
||||||
'url' => $image_url, |
|
||||||
'alt' => get_post_meta($image_id, '_wp_attachment_image_alt', true) |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return $images_array; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public function get_weight() { |
|
||||||
$custom_measurement = get_post_meta($this->id, '_custom_measurement', true) ?: pll__('кг'); |
|
||||||
$custom_size = get_post_meta($this->id, '_size_for_display', true) ?: ''; |
|
||||||
|
|
||||||
if ($custom_size){ |
|
||||||
return $custom_size ? $custom_size . ' ' . $custom_measurement : ''; |
|
||||||
} |
|
||||||
else{ |
|
||||||
if ($this->product && method_exists($this->product, 'get_weight')) { |
|
||||||
return $this->product->get_weight() ? $this->product->get_weight() . ' ' . $custom_measurement : ''; |
|
||||||
} |
|
||||||
return ''; |
|
||||||
} |
|
||||||
return ''; |
|
||||||
} |
|
||||||
|
|
||||||
public function getNumericWeight() { |
|
||||||
$custom_size = get_post_meta($this->id, '_size_for_display', true) ?: ''; |
|
||||||
|
|
||||||
if ($custom_size){ |
|
||||||
return floatval($custom_size); |
|
||||||
} |
|
||||||
else{ |
|
||||||
if ($this->product && method_exists($this->product, 'get_weight')) { |
|
||||||
return floatval($this->product->get_weight()); |
|
||||||
} |
|
||||||
return 0; |
|
||||||
} |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Получает CSS класс вкуса для товара |
|
||||||
* @return string CSS класс вкуса (например, --food-fish, --treats-beef) |
|
||||||
*/ |
|
||||||
public function getTasteClass() { |
|
||||||
// Получаем категории товара |
|
||||||
$product_categories = $this->product->get_category_ids(); |
|
||||||
|
|
||||||
$is_food = false; |
|
||||||
$is_treats = false; |
|
||||||
// Определяем тип товара (корм или лакомство) |
|
||||||
foreach ($product_categories as $cat) { |
|
||||||
if ($cat == 365) { |
|
||||||
$is_food = true; |
|
||||||
} elseif ($cat == 367) { |
|
||||||
$is_treats = true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Определяем префикс типа товара |
|
||||||
$type_prefix = ''; |
|
||||||
if ($is_food) { |
|
||||||
$type_prefix = 'food'; |
|
||||||
} elseif ($is_treats) { |
|
||||||
$type_prefix = 'treats'; |
|
||||||
} else { |
|
||||||
$type_prefix = 'acc'; // Дефолтный тип |
|
||||||
} |
|
||||||
|
|
||||||
// Получаем термины атрибута compound (вкус) |
|
||||||
$compound_terms = get_the_terms($this->id, 'pa_compound'); |
|
||||||
$taste_suffix = ''; |
|
||||||
|
|
||||||
if ($compound_terms && !is_wp_error($compound_terms)) { |
|
||||||
foreach ($compound_terms as $term) { |
|
||||||
switch ($term->slug) { |
|
||||||
case 'govyadina': |
|
||||||
$taste_suffix = 'beef'; |
|
||||||
break; |
|
||||||
case 'indejka': |
|
||||||
$taste_suffix = 'turkey'; |
|
||||||
break; |
|
||||||
case 'krolik': |
|
||||||
$taste_suffix = 'rabbit'; |
|
||||||
break; |
|
||||||
case 'losos': |
|
||||||
$taste_suffix = 'salmon'; |
|
||||||
break; |
|
||||||
case 'ryba': |
|
||||||
$taste_suffix = 'fish'; |
|
||||||
break; |
|
||||||
case 'utka': |
|
||||||
$taste_suffix = 'duck'; |
|
||||||
break; |
|
||||||
case 'yagnenok': |
|
||||||
$taste_suffix = 'lamb'; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// Если нашли вкус, прерываем цикл |
|
||||||
if ($taste_suffix) { |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Если вкус не найден, используем дефолтные суффиксы по типу товара |
|
||||||
if (!$taste_suffix) { |
|
||||||
if ($is_food) { |
|
||||||
$taste_suffix = 'fish'; |
|
||||||
} elseif ($is_treats) { |
|
||||||
$taste_suffix = 'beef'; |
|
||||||
} else { |
|
||||||
$taste_suffix = ''; // Дефолтный суффикс |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return '--' . $type_prefix . '-' . $taste_suffix; |
|
||||||
} |
|
||||||
|
|
||||||
public function getSizeSiblings() { |
|
||||||
|
|
||||||
$term = get_the_terms($this->id, 'pa_collection'); |
|
||||||
if ($term) { |
|
||||||
$term = $term[0]->term_id; |
|
||||||
} else { |
|
||||||
return []; |
|
||||||
} |
|
||||||
|
|
||||||
$args = array( |
|
||||||
'posts_per_page' => -1, |
|
||||||
'post_type' => 'product', |
|
||||||
'order' => 'ASC', |
|
||||||
'orderby' => 'name', // Fixed parameter name (was 'order_by') |
|
||||||
'tax_query' => [ |
|
||||||
[ |
|
||||||
'taxonomy' => 'pa_collection', |
|
||||||
'terms' => $term, |
|
||||||
'field' => 'id', |
|
||||||
] |
|
||||||
], |
|
||||||
); |
|
||||||
|
|
||||||
$siblings = Timber::get_posts($args); |
|
||||||
|
|
||||||
// Create array with products and their weights |
|
||||||
$siblings_with_weights = []; |
|
||||||
foreach ($siblings as $sibling) { |
|
||||||
$weight = $sibling->get_weight(); |
|
||||||
$siblings_with_weights[] = [ |
|
||||||
'post' => $sibling, |
|
||||||
'weight' => floatval($weight) // Ensure weight is treated as a number |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
// Sort by weight |
|
||||||
usort($siblings_with_weights, function($a, $b) { |
|
||||||
return $a['weight'] <=> $b['weight']; |
|
||||||
}); |
|
||||||
|
|
||||||
// Extract just the posts in sorted order |
|
||||||
$sorted_siblings = array_map(function($item) { |
|
||||||
return $item['post']; |
|
||||||
}, $siblings_with_weights); |
|
||||||
return $sorted_siblings; |
|
||||||
} |
|
||||||
|
|
||||||
protected function get_category_products(){ |
|
||||||
// Получаем все товары с похожими атрибутами |
|
||||||
$args = array( |
|
||||||
'posts_per_page' => -1, |
|
||||||
'post_type' => 'product', |
|
||||||
'order' => 'ASC', |
|
||||||
'orderby' => 'name', |
|
||||||
'post_status' => 'publish' |
|
||||||
); |
|
||||||
|
|
||||||
error_log("get_category_products: Запрос товаров"); |
|
||||||
$posts = Timber::get_posts($args); |
|
||||||
error_log("get_category_products: Получено товаров: " . (is_array($posts) ? count($posts) : 'не массив')); |
|
||||||
|
|
||||||
// Преобразуем в массив, если это PostCollection или PostQuery |
|
||||||
if ($posts instanceof \Timber\PostCollection || $posts instanceof \Timber\PostQuery) { |
|
||||||
$result = $posts->get_posts(); |
|
||||||
error_log("get_category_products: Преобразовано в массив: " . count($result)); |
|
||||||
return $result; |
|
||||||
} |
|
||||||
|
|
||||||
$result = is_array($posts) ? $posts : []; |
|
||||||
error_log("get_category_products: Возвращаем: " . count($result)); |
|
||||||
return $result; |
|
||||||
} |
|
||||||
|
|
||||||
public function getProductConstructor() { |
|
||||||
$all_products = $this->get_category_products(); |
|
||||||
$constructor = []; |
|
||||||
|
|
||||||
// Получаем атрибуты текущего товара |
|
||||||
$current_product_attributes = []; |
|
||||||
$current_weight = $this->getNumericWeight(); |
|
||||||
|
|
||||||
// Получаем значения атрибутов текущего товара |
|
||||||
foreach ($this->sibling_categories as $taxonomy) { |
|
||||||
$terms = get_the_terms($this->id, $taxonomy); |
|
||||||
if ($terms && !is_wp_error($terms)) { |
|
||||||
$current_product_attributes[$taxonomy] = array_map(function($term) { |
|
||||||
return $term->term_id; |
|
||||||
}, $terms); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Получаем упорядоченные таксономии |
|
||||||
$ordered_taxonomies = $this->getOrderedTaxonomies(); |
|
||||||
|
|
||||||
// Инициализируем конструктор для всех таксономий |
|
||||||
foreach ($this->sibling_categories as $taxonomy) { |
|
||||||
if (isset($current_product_attributes[$taxonomy])) { |
|
||||||
$constructor[$taxonomy] = [ |
|
||||||
'taxonomy' => $taxonomy, |
|
||||||
'label' => $this->getAttributeLabel($taxonomy), |
|
||||||
'current_value' => $this->getCurrentAttributeValue($taxonomy), |
|
||||||
'options' => [] |
|
||||||
]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// ОБХОДИМ МАССИВ ТОВАРОВ ТОЛЬКО ОДИН РАЗ |
|
||||||
foreach ($all_products as $product) { |
|
||||||
// Получаем все атрибуты сравниваемого товара за один раз |
|
||||||
$compare_attributes = []; |
|
||||||
$compare_weight = $product->getNumericWeight(); |
|
||||||
|
|
||||||
foreach ($this->sibling_categories as $taxonomy) { |
|
||||||
$terms = get_the_terms($product->id, $taxonomy); |
|
||||||
if ($terms && !is_wp_error($terms)) { |
|
||||||
$compare_attributes[$taxonomy] = array_map(function($term) { |
|
||||||
return $term->term_id; |
|
||||||
}, $terms); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Проверяем, подходит ли товар для каждой таксономии |
|
||||||
foreach ($this->sibling_categories as $taxonomy) { |
|
||||||
// Пропускаем, если у текущего товара нет значения для этой категории |
|
||||||
if (!isset($current_product_attributes[$taxonomy])) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
// Проверяем, совпадают ли все остальные атрибуты и вес |
|
||||||
$attributes_match = true; |
|
||||||
|
|
||||||
// Проверяем все атрибуты кроме текущей таксономии |
|
||||||
foreach ($this->sibling_categories as $compare_taxonomy) { |
|
||||||
if ($compare_taxonomy === $taxonomy) { |
|
||||||
continue; // Пропускаем проверяемую категорию |
|
||||||
} |
|
||||||
|
|
||||||
// Если у текущего товара есть значение для этой категории |
|
||||||
if (isset($current_product_attributes[$compare_taxonomy])) { |
|
||||||
// Проверяем, есть ли у сравниваемого товара значение для этой категории |
|
||||||
if (!isset($compare_attributes[$compare_taxonomy])) { |
|
||||||
$attributes_match = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// Проверяем, совпадают ли значения |
|
||||||
$current_values = $current_product_attributes[$compare_taxonomy]; |
|
||||||
$compare_values = $compare_attributes[$compare_taxonomy]; |
|
||||||
|
|
||||||
if (array_diff($current_values, $compare_values) !== [] || |
|
||||||
array_diff($compare_values, $current_values) !== []) { |
|
||||||
$attributes_match = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
// Если у текущего товара НЕТ значения для этой категории, |
|
||||||
// то у сравниваемого товара тоже не должно быть значения |
|
||||||
else { |
|
||||||
if (isset($compare_attributes[$compare_taxonomy])) { |
|
||||||
$attributes_match = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Проверяем вес (числовое сравнение) |
|
||||||
if (abs($current_weight - $compare_weight) > 0.01) { |
|
||||||
$attributes_match = false; |
|
||||||
} |
|
||||||
|
|
||||||
// Если все атрибуты и вес совпадают, добавляем товар в группу |
|
||||||
if ($attributes_match) { |
|
||||||
$product_terms = get_the_terms($product->id, $taxonomy); |
|
||||||
if ($product_terms && !is_wp_error($product_terms)) { |
|
||||||
foreach ($product_terms as $term) { |
|
||||||
$option_key = $term->term_id; |
|
||||||
if (!isset($constructor[$taxonomy]['options'][$option_key])) { |
|
||||||
$constructor[$taxonomy]['options'][$option_key] = [ |
|
||||||
'term_id' => $term->term_id, |
|
||||||
'name' => $this->getTermName($term->term_id, $taxonomy), |
|
||||||
'slug' => $term->slug, |
|
||||||
'icon' => $this->getTermIcon($term->term_id, $taxonomy), |
|
||||||
'products' => [] |
|
||||||
]; |
|
||||||
} |
|
||||||
$constructor[$taxonomy]['options'][$option_key]['products'][] = $product; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Сортируем опции по порядку терминов для каждой таксономии |
|
||||||
foreach ($constructor as $taxonomy => $taxonomy_data) { |
|
||||||
if (isset($ordered_taxonomies[$taxonomy])) { |
|
||||||
$ordered_options = []; |
|
||||||
foreach ($ordered_taxonomies[$taxonomy] as $term) { |
|
||||||
if (isset($constructor[$taxonomy]['options'][$term->term_id])) { |
|
||||||
$ordered_options[$term->term_id] = $constructor[$taxonomy]['options'][$term->term_id]; |
|
||||||
} |
|
||||||
} |
|
||||||
$constructor[$taxonomy]['options'] = $ordered_options; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
// Сортируем итоговый конструктор по порядку таксономий |
|
||||||
$ordered_constructor = []; |
|
||||||
foreach ($this->sibling_categories as $taxonomy) { |
|
||||||
if (isset($constructor[$taxonomy])) { |
|
||||||
$ordered_constructor[$taxonomy] = $constructor[$taxonomy]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return $ordered_constructor; |
|
||||||
} |
|
||||||
|
|
||||||
protected function getAttributeLabel($taxonomy) { |
|
||||||
// Fallback на старые метки |
|
||||||
$labels = [ |
|
||||||
'pa_age-of-the-cat' => pll__('ВОЗРАСТ КОШКИ'), |
|
||||||
'pa_age-of-the-dog' => pll__('ВОЗРАСТ СОБАКИ'), |
|
||||||
'pa_dog-size' => pll__('РАЗМЕР СОБАКИ'), |
|
||||||
'pa_compound' => pll__('ВКУС КОРМА'), |
|
||||||
'pa_reproductive-status' => pll__('ВИД КОШКИ'), |
|
||||||
'pa_series' => pll__('СЕРИЯ'), |
|
||||||
]; |
|
||||||
|
|
||||||
return $labels[$taxonomy] ?? wc_attribute_label($taxonomy); |
|
||||||
} |
|
||||||
|
|
||||||
protected function getCurrentAttributeValue($taxonomy) { |
|
||||||
$terms = get_the_terms($this->id, $taxonomy); |
|
||||||
if ($terms && !is_wp_error($terms)) { |
|
||||||
return $terms[0]->term_id; |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Получает таксономии в правильном порядке с учетом сортировки |
|
||||||
* @return array Массив таксономий с их порядком |
|
||||||
*/ |
|
||||||
protected function getOrderedTaxonomies() { |
|
||||||
$ordered_taxonomies = []; |
|
||||||
|
|
||||||
foreach ($this->sibling_categories as $taxonomy) { |
|
||||||
// Получаем все термины для данной таксономии |
|
||||||
$terms = get_terms([ |
|
||||||
'taxonomy' => $taxonomy, |
|
||||||
'hide_empty' => false, |
|
||||||
'orderby' => 'menu_order', |
|
||||||
'order' => 'ASC' |
|
||||||
]); |
|
||||||
|
|
||||||
// Если menu_order не работает, пробуем сортировку по name |
|
||||||
if (is_wp_error($terms) || empty($terms)) { |
|
||||||
$terms = get_terms([ |
|
||||||
'taxonomy' => $taxonomy, |
|
||||||
'hide_empty' => false, |
|
||||||
'orderby' => 'name', |
|
||||||
'order' => 'ASC' |
|
||||||
]); |
|
||||||
} |
|
||||||
|
|
||||||
if (!is_wp_error($terms) && !empty($terms)) { |
|
||||||
$ordered_taxonomies[$taxonomy] = $terms; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return $ordered_taxonomies; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Получает таксономии в правильном порядке для отображения |
|
||||||
* @return array Массив таксономий в порядке отображения |
|
||||||
*/ |
|
||||||
public function getOrderedSiblingCategories() { |
|
||||||
return $this->sibling_categories; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Получает таксономии с их метками в правильном порядке |
|
||||||
* @return array Массив таксономий с метками |
|
||||||
*/ |
|
||||||
public function getOrderedTaxonomiesWithLabels() { |
|
||||||
$taxonomies_with_labels = []; |
|
||||||
|
|
||||||
foreach ($this->sibling_categories as $taxonomy) { |
|
||||||
$label = $this->getAttributeLabel($taxonomy); |
|
||||||
$taxonomies_with_labels[$taxonomy] = $label; |
|
||||||
} |
|
||||||
|
|
||||||
return $taxonomies_with_labels; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Получает иконку термина из ACF поля |
|
||||||
* @param int $term_id ID термина |
|
||||||
* @param string $taxonomy Таксономия |
|
||||||
* @return string|false URL иконки или false если иконка не найдена |
|
||||||
*/ |
|
||||||
public function getTermIcon($term_id, $taxonomy) { |
|
||||||
// Проверяем, есть ли ACF поле 'icon' у термина |
|
||||||
$icon = get_field('icon', $taxonomy . '_' . $term_id); |
|
||||||
|
|
||||||
if ($icon) { |
|
||||||
return $icon; |
|
||||||
} |
|
||||||
|
|
||||||
// Если ACF поле не найдено, возвращаем false |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Получает название термина с приоритетом описания |
|
||||||
* @param int $term_id ID термина |
|
||||||
* @param string $taxonomy Таксономия |
|
||||||
* @return string Название термина |
|
||||||
*/ |
|
||||||
public function getTermName($term_id, $taxonomy) { |
|
||||||
$term = get_term($term_id, $taxonomy); |
|
||||||
|
|
||||||
if (!$term || is_wp_error($term)) { |
|
||||||
return ''; |
|
||||||
} |
|
||||||
|
|
||||||
// Сначала пытаемся получить описание термина |
|
||||||
$description = get_term_meta($term_id, 'description', true); |
|
||||||
|
|
||||||
// Также пробуем получить из ACF поля |
|
||||||
$acf_description = get_field('description', $taxonomy . '_' . $term_id); |
|
||||||
|
|
||||||
// Пробуем получить из стандартного поля термина |
|
||||||
$term_description = $term->description; |
|
||||||
|
|
||||||
// Пробуем ACF поле сначала |
|
||||||
if (!empty($acf_description)) { |
|
||||||
return $acf_description; |
|
||||||
} |
|
||||||
|
|
||||||
// Потом стандартное поле термина |
|
||||||
if (!empty($term_description)) { |
|
||||||
return $term_description; |
|
||||||
} |
|
||||||
|
|
||||||
// Потом обычное мета-поле |
|
||||||
if (!empty($description)) { |
|
||||||
return $description; |
|
||||||
} |
|
||||||
|
|
||||||
return $term->name; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Получает количество товара в корзине |
|
||||||
* @return int Количество товара в корзине |
|
||||||
*/ |
|
||||||
public function getCartQuantity() { |
|
||||||
if (!function_exists('WC') || !WC()->cart) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
$cart = WC()->cart; |
|
||||||
$cart_item_key = $this->getCartItemKey(); |
|
||||||
|
|
||||||
if ($cart_item_key) { |
|
||||||
$cart_item = $cart->get_cart_item($cart_item_key); |
|
||||||
return $cart_item ? $cart_item['quantity'] : 0; |
|
||||||
} |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Получает ключ товара в корзине |
|
||||||
* @return string|false Ключ товара в корзине или false если товар не найден |
|
||||||
*/ |
|
||||||
public function getCartItemKey() { |
|
||||||
if (!function_exists('WC') || !WC()->cart) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
$cart = WC()->cart; |
|
||||||
|
|
||||||
foreach ($cart->get_cart() as $cart_item_key => $cart_item) { |
|
||||||
if ($cart_item['product_id'] == $this->id) { |
|
||||||
return $cart_item_key; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Проверяет, есть ли товар в корзине |
|
||||||
* @return bool True если товар в корзине, false если нет |
|
||||||
*/ |
|
||||||
public function isInCart() { |
|
||||||
return $this->getCartQuantity() > 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function getAllAttributes() { |
|
||||||
$attributes = []; |
|
||||||
foreach ($this->sibling_categories as $taxonomy) { |
|
||||||
$terms = get_the_terms($this->id, $taxonomy); |
|
||||||
if ($terms && !is_wp_error($terms)) { |
|
||||||
$attributes[$taxonomy] = []; |
|
||||||
foreach ($terms as $term) { |
|
||||||
$attributes[$taxonomy][] = [ |
|
||||||
'term_id' => $term->term_id, |
|
||||||
'name' => $term->name, |
|
||||||
'slug' => $term->slug |
|
||||||
]; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return $attributes; |
|
||||||
} |
|
||||||
|
|
||||||
public function getPrice(){ |
|
||||||
$price = $this->product->get_price() . ' ' . get_woocommerce_currency_symbol(); |
|
||||||
return $price; |
|
||||||
} |
|
||||||
|
|
||||||
public function getRegularPrice(){ |
|
||||||
$regular_price = $this->product->get_regular_price() . ' ' . get_woocommerce_currency_symbol(); |
|
||||||
if ($regular_price != $this->getPrice()){ |
|
||||||
return $regular_price; |
|
||||||
} |
|
||||||
else{ |
|
||||||
return ''; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public function getPriceDifferenceInPercent(){ |
|
||||||
$regular_price = $this->product->get_regular_price(); |
|
||||||
$price = $this->product->get_price(); |
|
||||||
$difference = ($regular_price - $price) / $regular_price * 100; |
|
||||||
$difference = round($difference, 0) . '%'; |
|
||||||
return $difference; |
|
||||||
} |
|
||||||
|
|
||||||
public function getReviews(){ |
|
||||||
|
|
||||||
$reviews = get_posts(array( |
|
||||||
'post_type' => 'p_reviews', |
|
||||||
'numberposts' => -1, |
|
||||||
'meta_query' => array( |
|
||||||
array( |
|
||||||
'key' => 'products', |
|
||||||
'value' => '"' . $this->id . '"', |
|
||||||
'compare' => 'LIKE' |
|
||||||
) |
|
||||||
) |
|
||||||
)); |
|
||||||
|
|
||||||
return $reviews; |
|
||||||
} |
|
||||||
|
|
||||||
public function getRelatedProducts(){ |
|
||||||
$related_products = []; |
|
||||||
$related_products_ids = $this->product->get_upsell_ids(); |
|
||||||
if ($related_products_ids) { |
|
||||||
foreach ($related_products_ids as $related_id) { |
|
||||||
$related_product = Timber::get_post($related_id); |
|
||||||
if ($related_product) { |
|
||||||
$related_products[] = $related_product; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return $related_products; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
@ -1,20 +0,0 @@ |
|||||||
<?php |
|
||||||
use Timber\Timber; |
|
||||||
global $post; |
|
||||||
|
|
||||||
$context = Timber::get_context(); |
|
||||||
|
|
||||||
// Получаем текущий продукт |
|
||||||
$product_id = get_the_ID(); |
|
||||||
$product = wc_get_product($product_id); |
|
||||||
|
|
||||||
// Добавляем продукт в контекст |
|
||||||
$context['product'] = $product; |
|
||||||
$context['post'] = Timber::get_post(); |
|
||||||
|
|
||||||
include_module('shop'); |
|
||||||
include_component('shop', 'reviews'); |
|
||||||
|
|
||||||
?> |
|
||||||
<?php |
|
||||||
Timber::render('woocommerce/single-product.twig', $context); |
|
@ -1,49 +0,0 @@ |
|||||||
/* Стили для загрузки корзины на single странице */ |
|
||||||
|
|
||||||
.product-incart__wrap.loading { |
|
||||||
position: relative; |
|
||||||
pointer-events: none; |
|
||||||
opacity: 0.7; |
|
||||||
} |
|
||||||
|
|
||||||
.product-incart__wrap.loading::before { |
|
||||||
content: ''; |
|
||||||
position: absolute; |
|
||||||
top: 0; |
|
||||||
left: 0; |
|
||||||
right: 0; |
|
||||||
bottom: 0; |
|
||||||
background: rgba(255, 255, 255, 0.8); |
|
||||||
z-index: 10; |
|
||||||
} |
|
||||||
|
|
||||||
.product-incart__wrap.loading::after { |
|
||||||
content: ''; |
|
||||||
position: absolute; |
|
||||||
top: 50%; |
|
||||||
left: 50%; |
|
||||||
width: 20px; |
|
||||||
height: 20px; |
|
||||||
margin: -10px 0 0 -10px; |
|
||||||
border: 2px solid #f3f3f3; |
|
||||||
border-top: 2px solid #3498db; |
|
||||||
border-radius: 50%; |
|
||||||
animation: spin 1s linear infinite; |
|
||||||
z-index: 11; |
|
||||||
} |
|
||||||
|
|
||||||
@keyframes spin { |
|
||||||
0% { transform: rotate(0deg); } |
|
||||||
100% { transform: rotate(360deg); } |
|
||||||
} |
|
||||||
|
|
||||||
/* Стили для кнопок во время загрузки */ |
|
||||||
.product-incart__wrap.loading .product-incart__btn { |
|
||||||
opacity: 0.5; |
|
||||||
pointer-events: none; |
|
||||||
} |
|
||||||
|
|
||||||
/* Стили для счетчика во время загрузки */ |
|
||||||
.product-incart__wrap.loading .product-incart__count { |
|
||||||
opacity: 0.5; |
|
||||||
} |
|
@ -1,156 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
$product; |
|
||||||
$product_type; |
|
||||||
$context_for_twig; |
|
||||||
|
|
||||||
// Получаем данные продукта |
|
||||||
$product_id = get_the_ID(); |
|
||||||
$product = wc_get_product($product_id); |
|
||||||
|
|
||||||
// Проверяем, что продукт существует |
|
||||||
if (!$product) { |
|
||||||
return; // Просто выходим, если продукт не найден |
|
||||||
} |
|
||||||
|
|
||||||
$attributes = []; |
|
||||||
$product_attributes = $product->get_attributes(); |
|
||||||
|
|
||||||
/* Получение категорий */ |
|
||||||
$tags = get_the_terms($product_id, 'product_cat'); |
|
||||||
if (!empty($tags) && !is_wp_error($tags)) { |
|
||||||
foreach ($tags as $tag) { |
|
||||||
$context_for_twig['product_tags'][] = $tag->name; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* Получение атрибутов */ |
|
||||||
if (!empty($product_attributes)) { |
|
||||||
foreach ($product_attributes as $taxonomy => $attribute) { |
|
||||||
if ($attribute->is_taxonomy()) { |
|
||||||
$terms = wc_get_product_terms($product_id, $taxonomy, ['fields' => 'all']); |
|
||||||
// $tags = wc_get_product_terms( $product_id, 'pa_catalog_tags' ); |
|
||||||
|
|
||||||
if (!empty($terms)) { |
|
||||||
$attr_values = []; |
|
||||||
foreach ($terms as $term) { |
|
||||||
$attr_values[] = [ |
|
||||||
'name' => $term->name, |
|
||||||
'slug' => $term->slug, |
|
||||||
'term_id' => $term->term_id, |
|
||||||
'link' => get_term_link($term->term_id, $taxonomy), |
|
||||||
]; |
|
||||||
} |
|
||||||
$attributes[wc_attribute_label($taxonomy)] = $attr_values; |
|
||||||
} |
|
||||||
} else { |
|
||||||
$attributes[wc_attribute_label($taxonomy)] = $attribute->get_options(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
$context_for_twig['product_attributes'] = $attributes; |
|
||||||
|
|
||||||
/* Получение вариаций товара */ |
|
||||||
if ($product->is_type('variable')) { |
|
||||||
$available_variations = $product->get_available_variations(); |
|
||||||
$variations_data = []; |
|
||||||
|
|
||||||
foreach ($available_variations as $variation) { |
|
||||||
$variation_id = $variation['variation_id']; |
|
||||||
$variation_obj = wc_get_product($variation_id); |
|
||||||
|
|
||||||
$variations_data[] = [ |
|
||||||
'variation_id' => $variation_id, |
|
||||||
'price' => $variation_obj->get_price(), |
|
||||||
'regular_price' => $variation_obj->get_regular_price(), |
|
||||||
'sale_price' => $variation_obj->get_sale_price(), |
|
||||||
'attributes' => $variation['attributes'] |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
$context_for_twig['variations'] = $variations_data; |
|
||||||
} |
|
||||||
|
|
||||||
/* ACF-поля и мета-данные продукта */ |
|
||||||
$meta_fields = [ |
|
||||||
'composition' => get_post_meta($product_id, '_composition', true), |
|
||||||
'feeding_recommendations' => get_post_meta($product_id, '_feeding_recommendations', true), // Ранее выводились HTML-полем «Рекомендации по кормлению» |
|
||||||
'feeding_recommendations_table' => get_field('feeding_recommendations_table', get_post(get_field('p_tables_field', $product_id))) , // Таблица «Рекомендации по кормлению» |
|
||||||
'nutritional_value' => get_post_meta($product_id, '_nutritional_value', true), |
|
||||||
'vitamins' => get_post_meta($product_id, '_vitamins', true), |
|
||||||
'additives' => get_post_meta($product_id, '_additives', true), |
|
||||||
'energy_value' => get_post_meta($product_id, '_energy_value', true), |
|
||||||
'important' => get_post_meta($product_id, '_important', true), |
|
||||||
]; |
|
||||||
|
|
||||||
$context_for_twig['product_meta'] = $meta_fields; |
|
||||||
|
|
||||||
|
|
||||||
/* Товар оформляется по подписке? */ |
|
||||||
$context_for_twig['is_subscription'] = $product->is_type( array( 'subscription', 'subscription_variation', 'variable-subscription' )) ? true : false; |
|
||||||
|
|
||||||
$context = Timber::get_context(); |
|
||||||
$post = Timber::get_post(); |
|
||||||
$context['post'] = $post; |
|
||||||
$context['wc_breadcrumbs'] = array(); |
|
||||||
|
|
||||||
if (function_exists('woocommerce_breadcrumb')) { |
|
||||||
$args = array( |
|
||||||
'delimiter' => '', |
|
||||||
'wrap_before' => '', |
|
||||||
'wrap_after' => '', |
|
||||||
'before' => '', |
|
||||||
'after' => '', |
|
||||||
'home' => _x('Home', 'breadcrumb', 'woocommerce'), |
|
||||||
); |
|
||||||
|
|
||||||
$breadcrumbs = new WC_Breadcrumb(); |
|
||||||
$breadcrumbs->generate(); |
|
||||||
|
|
||||||
$formatted_breadcrumbs = array(); |
|
||||||
foreach ($breadcrumbs->get_breadcrumb() as $crumb) { |
|
||||||
$formatted_breadcrumbs[] = array( |
|
||||||
'text' => $crumb[0], |
|
||||||
'url' => $crumb[1] |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
$context['wc_breadcrumbs'] = $formatted_breadcrumbs; |
|
||||||
} |
|
||||||
|
|
||||||
$context['product'] = $product; |
|
||||||
|
|
||||||
$context['related_products'] = array(); |
|
||||||
$related_products_ids = $product->get_upsell_ids(); |
|
||||||
if ($related_products_ids) { |
|
||||||
foreach ($related_products_ids as $related_id) { |
|
||||||
$related_product = wc_get_product($related_id); |
|
||||||
if ($related_product) { |
|
||||||
$context['related_products'][] = $related_product; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
if (class_exists('WCS_ATT_Product_Schemes')) { |
|
||||||
$schemes = WCS_ATT_Product_Schemes::get_subscription_schemes($product); |
|
||||||
$context['has_subscription_options'] = !empty($schemes); |
|
||||||
} else { |
|
||||||
$context['has_subscription_options'] = false; |
|
||||||
} |
|
||||||
|
|
||||||
Timber::render('_pages/shop/product-single.twig', $context); |
|
||||||
|
|
||||||
// Подключение стилей для загрузки корзины |
|
||||||
add_action('wp_enqueue_scripts', 'single_product_cart_styles'); |
|
||||||
|
|
||||||
function single_product_cart_styles() { |
|
||||||
if (is_product()) { |
|
||||||
wp_enqueue_style( |
|
||||||
'single-product-cart-loading', |
|
||||||
get_template_directory_uri() . '/modules/shop/components/single-product/assets/css/cart-loading.css', |
|
||||||
array(), |
|
||||||
'1.0.0' |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 459 B After Width: | Height: | Size: 459 B |
Before Width: | Height: | Size: 481 B After Width: | Height: | Size: 481 B |
Before Width: | Height: | Size: 456 B After Width: | Height: | Size: 456 B |
Before Width: | Height: | Size: 458 B After Width: | Height: | Size: 458 B |
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 954 B |
Before Width: | Height: | Size: 455 B After Width: | Height: | Size: 455 B |
@ -0,0 +1,152 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
$product; |
||||||
|
$product_type; |
||||||
|
$context_for_twig; |
||||||
|
|
||||||
|
if (function_exists('is_product') && is_product()) { |
||||||
|
$product_id = get_the_ID(); |
||||||
|
$product = wc_get_product($product_id); |
||||||
|
|
||||||
|
$attributes = []; |
||||||
|
$product_attributes = $product->get_attributes(); |
||||||
|
|
||||||
|
/* Получение категорий */ |
||||||
|
$tags = get_the_terms($product_id, 'product_cat'); |
||||||
|
if (!empty($tags) && !is_wp_error($tags)) { |
||||||
|
foreach ($tags as $tag) { |
||||||
|
$context_for_twig['product_tags'][] = $tag->name; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Получение атрибутов */ |
||||||
|
if (!empty($product_attributes)) { |
||||||
|
foreach ($product_attributes as $taxonomy => $attribute) { |
||||||
|
if ($attribute->is_taxonomy()) { |
||||||
|
$terms = wc_get_product_terms($product_id, $taxonomy, ['fields' => 'all']); |
||||||
|
// $tags = wc_get_product_terms( $product_id, 'pa_catalog_tags' ); |
||||||
|
|
||||||
|
if (!empty($terms)) { |
||||||
|
$attr_values = []; |
||||||
|
foreach ($terms as $term) { |
||||||
|
$attr_values[] = [ |
||||||
|
'name' => $term->name, |
||||||
|
'slug' => $term->slug, |
||||||
|
'term_id' => $term->term_id, |
||||||
|
'link' => get_term_link($term->term_id, $taxonomy), |
||||||
|
]; |
||||||
|
} |
||||||
|
$attributes[wc_attribute_label($taxonomy)] = $attr_values; |
||||||
|
} |
||||||
|
} else { |
||||||
|
$attributes[wc_attribute_label($taxonomy)] = $attribute->get_options(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$context_for_twig['product_attributes'] = $attributes; |
||||||
|
|
||||||
|
/* Получение вариаций товара */ |
||||||
|
if ($product->is_type('variable')) { |
||||||
|
$available_variations = $product->get_available_variations(); |
||||||
|
$variations_data = []; |
||||||
|
|
||||||
|
foreach ($available_variations as $variation) { |
||||||
|
$variation_id = $variation['variation_id']; |
||||||
|
$variation_obj = wc_get_product($variation_id); |
||||||
|
|
||||||
|
$variations_data[] = [ |
||||||
|
'variation_id' => $variation_id, |
||||||
|
'price' => $variation_obj->get_price(), |
||||||
|
'regular_price' => $variation_obj->get_regular_price(), |
||||||
|
'sale_price' => $variation_obj->get_sale_price(), |
||||||
|
'attributes' => $variation['attributes'] |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
$context_for_twig['variations'] = $variations_data; |
||||||
|
} |
||||||
|
|
||||||
|
/* ACF-поля и мета-данные продукта */ |
||||||
|
$meta_fields = [ |
||||||
|
'composition' => get_post_meta($product_id, '_composition', true), |
||||||
|
'feeding_recommendations' => get_post_meta($product_id, '_feeding_recommendations', true), // Ранее выводились HTML-полем «Рекомендации по кормлению» |
||||||
|
'feeding_recommendations_table' => get_field('feeding_recommendations_table', get_post(get_field('p_tables_field', $product_id))) , // Таблица «Рекомендации по кормлению» |
||||||
|
'nutritional_value' => get_post_meta($product_id, '_nutritional_value', true), |
||||||
|
'vitamins' => get_post_meta($product_id, '_vitamins', true), |
||||||
|
'additives' => get_post_meta($product_id, '_additives', true), |
||||||
|
'energy_value' => get_post_meta($product_id, '_energy_value', true), |
||||||
|
'important' => get_post_meta($product_id, '_important', true), |
||||||
|
]; |
||||||
|
|
||||||
|
$context_for_twig['product_meta'] = $meta_fields; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Товар оформляется по подписке? */ |
||||||
|
$context_for_twig['is_subscription'] = $product->is_type( array( 'subscription', 'subscription_variation', 'variable-subscription' )) ? true : false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
add_filter('timber/context', function ($context) use ($context_for_twig) { |
||||||
|
return array_merge($context, $context_for_twig); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$context = Timber::get_context(); |
||||||
|
$post = Timber::get_post(); |
||||||
|
$context['post'] = $post; |
||||||
|
|
||||||
|
$context['wc_breadcrumbs'] = array(); |
||||||
|
|
||||||
|
if (function_exists('woocommerce_breadcrumb')) { |
||||||
|
$args = array( |
||||||
|
'delimiter' => '', |
||||||
|
'wrap_before' => '', |
||||||
|
'wrap_after' => '', |
||||||
|
'before' => '', |
||||||
|
'after' => '', |
||||||
|
'home' => _x('Home', 'breadcrumb', 'woocommerce'), |
||||||
|
); |
||||||
|
|
||||||
|
$breadcrumbs = new WC_Breadcrumb(); |
||||||
|
$breadcrumbs->generate(); |
||||||
|
|
||||||
|
$formatted_breadcrumbs = array(); |
||||||
|
foreach ($breadcrumbs->get_breadcrumb() as $crumb) { |
||||||
|
$formatted_breadcrumbs[] = array( |
||||||
|
'text' => $crumb[0], |
||||||
|
'url' => $crumb[1] |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
$context['wc_breadcrumbs'] = $formatted_breadcrumbs; |
||||||
|
} |
||||||
|
|
||||||
|
$product_id = get_the_ID(); |
||||||
|
$product = wc_get_product($product_id); |
||||||
|
|
||||||
|
$context['product'] = $product; |
||||||
|
|
||||||
|
$context['related_products'] = array(); |
||||||
|
$related_products_ids = $product->get_upsell_ids(); |
||||||
|
if ($related_products_ids) { |
||||||
|
foreach ($related_products_ids as $related_id) { |
||||||
|
$related_product = wc_get_product($related_id); |
||||||
|
if ($related_product) { |
||||||
|
$context['related_products'][] = $related_product; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (class_exists('WCS_ATT_Product_Schemes')) { |
||||||
|
$schemes = WCS_ATT_Product_Schemes::get_subscription_schemes($product); |
||||||
|
$context['has_subscription_options'] = !empty($schemes); |
||||||
|
} else { |
||||||
|
$context['has_subscription_options'] = false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
Timber::render('_pages/shop/product-single.twig', $context); |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 459 B After Width: | Height: | Size: 459 B |
Before Width: | Height: | Size: 481 B After Width: | Height: | Size: 481 B |
Before Width: | Height: | Size: 456 B After Width: | Height: | Size: 456 B |
Before Width: | Height: | Size: 458 B After Width: | Height: | Size: 458 B |
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 954 B |
Before Width: | Height: | Size: 455 B After Width: | Height: | Size: 455 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1,29 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$context = Timber::get_context(); |
||||||
|
|
||||||
|
include_component('shop', 'reviews'); |
||||||
|
include_component('shop', 'product-card'); |
||||||
|
|
||||||
|
$reviews = get_posts(array( |
||||||
|
'post_type' => 'p_reviews', |
||||||
|
'numberposts' => -1, |
||||||
|
)); |
||||||
|
|
||||||
|
$product_id = get_the_ID(); |
||||||
|
$product = wc_get_product($product_id); |
||||||
|
$context['related_products'] = array(); |
||||||
|
$related_products_ids = $product->get_upsell_ids(); |
||||||
|
if ($related_products_ids) { |
||||||
|
foreach ($related_products_ids as $related_id) { |
||||||
|
$related_product = wc_get_product($related_id); |
||||||
|
if ($related_product) { |
||||||
|
$context['related_products'][] = $related_product; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$context['reviews'] = $reviews; |
||||||
|
Timber::render('shop/single-product_page.twig', $context); |
@ -0,0 +1,6 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
include_module('author'); |
||||||
|
include_component('author', 'author-single'); |
||||||
|
|
||||||
|
?> |
@ -0,0 +1,6 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
include_module('blog'); |
||||||
|
include_component('blog', 'single'); |
||||||
|
|
||||||
|
?> |
@ -0,0 +1,21 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) { |
||||||
|
exit; |
||||||
|
} |
||||||
|
|
||||||
|
if (is_product()) { |
||||||
|
|
||||||
|
include_module('shop'); |
||||||
|
global $product; |
||||||
|
// Get the product ID |
||||||
|
$product_id = get_the_ID(); |
||||||
|
if ($product_id == 1105){ |
||||||
|
include_component('shop', 'single-product_new'); |
||||||
|
} |
||||||
|
else{ |
||||||
|
include_component('shop', 'single-product'); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -1,26 +0,0 @@ |
|||||||
<?php |
|
||||||
/** |
|
||||||
* The Template for displaying all single posts |
|
||||||
* |
|
||||||
* @link https://developer.wordpress.org/themes/basics/template-hierarchy/ |
|
||||||
*/ |
|
||||||
|
|
||||||
namespace App; |
|
||||||
|
|
||||||
use Timber\Timber; |
|
||||||
|
|
||||||
$context = Timber::context(); |
|
||||||
$post = $context['post']; |
|
||||||
|
|
||||||
if ( is_singular('post') ) { |
|
||||||
include_module('blog'); |
|
||||||
include_component('blog', 'single'); |
|
||||||
} elseif ( is_singular('blog_author') ) { |
|
||||||
include_module('author'); |
|
||||||
include_component('author', 'author-single'); |
|
||||||
} else { |
|
||||||
// Для других типов записей |
|
||||||
$templates = [ 'views/single-' . get_post_type() . '.twig', 'views/single.twig' ]; |
|
||||||
} |
|
||||||
|
|
||||||
Timber::render( $templates, $context ); |
|
@ -1,56 +1,71 @@ |
|||||||
<? |
<? |
||||||
|
|
||||||
use Timber; |
use Timber; |
||||||
use Timber\PostCollection; |
use Timber\PostCollection; |
||||||
use Timber\Integrations\WooCommerce\Product as TimberProduct; |
use Timber\Integrations\WooCommerce\Product as TimberProduct; |
||||||
|
|
||||||
|
|
||||||
Timber::$dirname = [ |
Timber::$dirname = [ |
||||||
'views', |
[ |
||||||
'modules' |
'modules', |
||||||
]; |
'templates' |
||||||
|
], |
||||||
// Настройка путей для WooCommerce шаблонов |
]; |
||||||
add_filter('timber/loader/paths', function($paths) { |
|
||||||
$paths[] = get_template_directory() . '/views/woocommerce'; |
|
||||||
return $paths; |
add_filter( 'timber/integrations', function ( array $integrations ): array { |
||||||
}); |
$integrations[] = new \Timber\Integrations\WooCommerce\WooCommerceIntegration(); |
||||||
|
return $integrations; |
||||||
add_filter( 'timber/integrations', function ( array $integrations ): array { |
} ); |
||||||
$integrations[] = new \Timber\Integrations\WooCommerce\WooCommerceIntegration(); |
|
||||||
return $integrations; |
add_action('timber/init', function() { |
||||||
} ); |
// Инициализируем WooCommerce интеграцию |
||||||
|
if (class_exists('Timber\Integrations\WooCommerce\WooCommerce')) { |
||||||
|
Timber\Integrations\WooCommerce\WooCommerce::init(); |
||||||
// Add the function to the Timber context |
} |
||||||
add_filter('timber/context', function($context) { |
}); |
||||||
$context['template_path'] = get_template_directory_uri(); |
|
||||||
$current_url = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; |
|
||||||
$context['current_url'] = htmlspecialchars($current_url); |
// Add the function to the Timber context |
||||||
|
add_filter('timber/context', function($context) { |
||||||
// Добавляем WooCommerce контекст если WooCommerce активен |
$context['template_path'] = get_template_directory_uri(); |
||||||
if (class_exists('WooCommerce')) { |
$current_url = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; |
||||||
// WooCommerce автоматически добавляет свой контекст через интеграцию |
$context['current_url'] = htmlspecialchars($current_url); |
||||||
// Но мы можем его расширить |
return $context; |
||||||
if (is_woocommerce()) { |
}); |
||||||
$context['is_woocommerce'] = true; |
|
||||||
} |
|
||||||
} |
add_action('init', function() { |
||||||
|
add_filter('timber/context', function($context) { |
||||||
return $context; |
$context['current_lang'] = pll_current_language(); |
||||||
}); |
return $context; |
||||||
|
}); |
||||||
|
}, 1); |
||||||
add_action('init', function() { |
|
||||||
add_filter('timber/context', function($context) { |
class WooProduct extends Timber\Post { |
||||||
$context['current_lang'] = pll_current_language(); |
protected $wc_product; |
||||||
|
|
||||||
// Добавляем функцию для получения иконки термина |
public function __construct ($pid = null) { |
||||||
$context['get_term_icon'] = function($term_id, $taxonomy) { |
parent::__construct($pid); |
||||||
$product = new CosmopetProduct(); |
$this->wc_product = wc_get_product($this->ID); |
||||||
return $product->getTermIcon($term_id, $taxonomy); |
} |
||||||
}; |
|
||||||
|
public function price() { |
||||||
return $context; |
return $this->wc_product->get_price(); |
||||||
}); |
} |
||||||
}, 1); |
|
||||||
|
public function get_price_html() { |
||||||
|
return $this->wc_product->get_price_html(); |
||||||
|
} |
||||||
|
|
||||||
|
public function get_attr() { |
||||||
|
return $this->wc_product->get_attribute('pa_compound'); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
add_filter('timber/post/classmap', function ($classmap) { |
||||||
|
$custom_classmap = [ |
||||||
|
'product' => WooProduct::class, |
||||||
|
]; |
||||||
|
return array_merge($classmap, $custom_classmap); |
||||||
|
}); |
||||||
|
@ -1,9 +1,5 @@ |
|||||||
{% for post in posts %} |
{% for post in posts %} |
||||||
|
{% include '_blocks/shop/archive-product-tease.twig' with {post: post} %} |
||||||
{% set class = post.getTasteClass %} |
|
||||||
{% set section = class ~ ' product-archive-card' %} |
|
||||||
{% include 'shop/product-card.twig' with {_product : fn('wc_get_product', post.id), section: section} %} |
|
||||||
|
|
||||||
{% endfor %} |
{% endfor %} |
||||||
|
|
||||||
{% if not ended %} |
{% if not ended %} |