Compare commits
3 Commits
377cabf3cc
...
8e354cb729
Author | SHA1 | Date |
---|---|---|
|
8e354cb729 | 7 days ago |
|
7499a8aa24 | 1 week ago |
|
6e2a763cb7 | 1 week ago |
@ -0,0 +1,380 @@ |
|||||||
|
<? |
||||||
|
|
||||||
|
/** |
||||||
|
* Добавление событий контрибуции для 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'; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
<? |
||||||
|
|
||||||
|
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"; |
||||||
|
} |
||||||
|
}); |
@ -0,0 +1,661 @@ |
|||||||
|
<?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; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
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,20 @@ |
|||||||
|
<?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); |
@ -0,0 +1,49 @@ |
|||||||
|
/* Стили для загрузки корзины на 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; |
||||||
|
} |
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,156 @@ |
|||||||
|
<?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' |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -1,152 +0,0 @@ |
|||||||
<?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); |
|
@ -1,29 +0,0 @@ |
|||||||
<?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); |
|
@ -1,6 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
include_module('author'); |
|
||||||
include_component('author', 'author-single'); |
|
||||||
|
|
||||||
?> |
|
@ -1,6 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
include_module('blog'); |
|
||||||
include_component('blog', 'single'); |
|
||||||
|
|
||||||
?> |
|
@ -1,21 +0,0 @@ |
|||||||
<?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'); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,26 @@ |
|||||||
|
<?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,71 +1,56 @@ |
|||||||
<? |
<? |
||||||
|
|
||||||
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'; |
||||||
add_filter( 'timber/integrations', function ( array $integrations ): array { |
return $paths; |
||||||
$integrations[] = new \Timber\Integrations\WooCommerce\WooCommerceIntegration(); |
}); |
||||||
return $integrations; |
|
||||||
} ); |
add_filter( 'timber/integrations', function ( array $integrations ): array { |
||||||
|
$integrations[] = new \Timber\Integrations\WooCommerce\WooCommerceIntegration(); |
||||||
add_action('timber/init', function() { |
return $integrations; |
||||||
// Инициализируем 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']; |
||||||
// Add the function to the Timber context |
$context['current_url'] = htmlspecialchars($current_url); |
||||||
add_filter('timber/context', function($context) { |
|
||||||
$context['template_path'] = get_template_directory_uri(); |
// Добавляем WooCommerce контекст если WooCommerce активен |
||||||
$current_url = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; |
if (class_exists('WooCommerce')) { |
||||||
$context['current_url'] = htmlspecialchars($current_url); |
// WooCommerce автоматически добавляет свой контекст через интеграцию |
||||||
return $context; |
// Но мы можем его расширить |
||||||
}); |
if (is_woocommerce()) { |
||||||
|
$context['is_woocommerce'] = true; |
||||||
|
} |
||||||
add_action('init', function() { |
} |
||||||
add_filter('timber/context', function($context) { |
|
||||||
$context['current_lang'] = pll_current_language(); |
return $context; |
||||||
return $context; |
}); |
||||||
}); |
|
||||||
}, 1); |
|
||||||
|
add_action('init', function() { |
||||||
class WooProduct extends Timber\Post { |
add_filter('timber/context', function($context) { |
||||||
protected $wc_product; |
$context['current_lang'] = pll_current_language(); |
||||||
|
|
||||||
public function __construct ($pid = null) { |
// Добавляем функцию для получения иконки термина |
||||||
parent::__construct($pid); |
$context['get_term_icon'] = function($term_id, $taxonomy) { |
||||||
$this->wc_product = wc_get_product($this->ID); |
$product = new CosmopetProduct(); |
||||||
} |
return $product->getTermIcon($term_id, $taxonomy); |
||||||
|
}; |
||||||
public function price() { |
|
||||||
return $this->wc_product->get_price(); |
return $context; |
||||||
} |
}); |
||||||
|
}, 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,19 +0,0 @@ |
|||||||
{% extends 'profile/profile-base.twig' %} |
|
||||||
|
|
||||||
{% block profile_content%} |
|
||||||
<div class="cabinet__orders cabinet-content {% if fn('is_wc_endpoint_url') %}active hide{% endif %}"> |
|
||||||
<!-- <div class="cabinet-card cabinet-card--green-white cabinet__subscription-pc"> |
|
||||||
<div class="cabinet-card__content"> |
|
||||||
<p class="cabinet-card__title">{{ function('pll_e', 'Feed subscription') }}</p> |
|
||||||
<div class="cabinet-card__element"> |
|
||||||
<p class="cabinet-card__text">{{ function('pll_e', 'Weekly food delivery for your pet') }}</p> |
|
||||||
</div> |
|
||||||
<div class="cabinet-card__element"> |
|
||||||
<button class="button button--gradient button--high-46 form-sub__btn">{{ function('pll_e', 'Get details') }}</button> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> --> |
|
||||||
{% include 'profile/order-list.twig' %} |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
{% endblock %} |
|
@ -1,27 +0,0 @@ |
|||||||
{% set profile_pg = 1 %} |
|
||||||
|
|
||||||
{% extends 'profile/profile-base.twig' %} |
|
||||||
|
|
||||||
{% block profile_content%} |
|
||||||
<div class="cabinet__orders cabinet-content {% if fn('is_wc_endpoint_url') %}active hide{% endif %}"> |
|
||||||
<!-- <div class="cabinet-card cabinet-card--green-white cabinet__subscription-pc"> |
|
||||||
<div class="cabinet-card__content"> |
|
||||||
<p class="cabinet-card__title">{{ function('pll_e', 'Feed subscription') }}</p> |
|
||||||
<div class="cabinet-card__element"> |
|
||||||
<p class="cabinet-card__text">{{ function('pll_e', 'Weekly food delivery for your pet') }}</p> |
|
||||||
</div> |
|
||||||
<div class="cabinet-card__element"> |
|
||||||
<button class="button button--gradient button--high-46 form-sub__btn">{{ function('pll_e', 'Get details') }}</button> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> --> |
|
||||||
{% include 'profile/order-list.twig' %} |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
|
|
||||||
</main> |
|
||||||
|
|
||||||
|
|
||||||
{% endblock %} |
|
||||||
|
|
@ -1,5 +1,9 @@ |
|||||||
{% 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 %} |
@ -0,0 +1,26 @@ |
|||||||
|
{% set in_stock = post.meta('_stock_status') == 'instock' %} |
||||||
|
|
||||||
|
{% set cart_quantity = post.getCartQuantity %} |
||||||
|
{% if in_stock %} |
||||||
|
{% if post.getCartQuantity == 0 %} |
||||||
|
{{ function('do_action', 'woocommerce_' ~ post.product.get_type() ~ '_add_to_cart') }} |
||||||
|
{% else %} |
||||||
|
<div class="product-incart__wrap" data-product-id="{{ post.id }}"> |
||||||
|
<div class="product-incart counter"> |
||||||
|
<button class="product-incart__btn product-incart__btn--minus" data-key="{{post.getCartItemKey}}" data-action="decrease"></button> |
||||||
|
|
||||||
|
<div class="product-incart__count" data-key="{{post.getCartItemKey}}">{{ cart_quantity }}</div> |
||||||
|
<button class="product-incart__btn product-incart__btn--plus" data-key="{{post.getCartItemKey}}" data-action="increase"></button> |
||||||
|
</div> |
||||||
|
<div class="product-incart__label"> |
||||||
|
{{fn('pll_e', 'В корзине')}} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{% endif %} |
||||||
|
{% else %} |
||||||
|
<div class="detail-block-form__item detail-block-form__item--tn"> |
||||||
|
<button type="button" data-pname="{{ product.title }}" class="to-know open-to-know" > |
||||||
|
<p>{{ function('pll_e', 'Узнать о поступлении') }}</p> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
{% endif %} |