0
X
Add Snippet To Project
New Project
Add To Existing Project
<?php
function my_theme_enqueue_styles(): void
{
$timestamp = time();
wp_enqueue_style('sc-success-style', get_stylesheet_directory_uri() . '/css/style.css?v=' . $timestamp, array(), filemtime(get_stylesheet_directory() . '/css/style.css'), 'all');
}
add_action('wp_enqueue_scripts', 'my_theme_enqueue_styles');
function enqueue_custom_scripts()
{
$timestamp = time();
wp_enqueue_script('bootstrap', 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js');
wp_enqueue_script('sc-success-script', get_template_directory_uri() . '/js/scripts.js?v=' . $timestamp, array('jquery'), '1.0', true);
wp_enqueue_script('sc-success-product-js', get_template_directory_uri() . '/js/product.js?v=' . $timestamp, array('jquery'), '1.0', true);
wp_enqueue_script('sc-success-shopping-cart-js', get_template_directory_uri() . '/js/cart.js?v=' . $timestamp, array('jquery'), '1.0', true);
wp_enqueue_script('sc-success-dropdown-js', get_template_directory_uri() . '/js/dropdown.js?v=' . $timestamp, array('jquery'), '1.0', true);
wp_localize_script('sc-success-product-js', 'ajax_object', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('fetch_product_template_nonce'),
]);
}
add_action('wp_enqueue_scripts', 'enqueue_custom_scripts');
function enqueue_slick_scripts()
{
// Enqueue Slick slider CSS
wp_enqueue_style('slick-css', 'https://cdn.jsdelivr.net/npm/slick-carousel/slick/slick.css', array(), '1.8.1');
// Enqueue Slick slider JavaScript
wp_enqueue_script('slick-js', 'https://cdn.jsdelivr.net/npm/slick-carousel/slick/slick.min.js', array('jquery'), '1.8.1', true);
}
add_action('wp_enqueue_scripts', 'enqueue_slick_scripts');
function custom_add_to_cart()
{
$product_id = $_POST['product_id'];
$quantity = 1; // Adjust based on your needs
WC()->cart->add_to_cart($product_id, $quantity);
$cart_total = WC()->cart->get_cart_contents_count(); // Get updated cart item count
wp_send_json_success(array('cart_total' => $cart_total));
}
add_action('wp_ajax_custom_add_to_cart', 'custom_add_to_cart');
add_action('wp_ajax_nopriv_custom_add_to_cart', 'custom_add_to_cart');
/**
* @param WC_Product $product
* @param $attribute_name
* @return array
*/
function get_product_color_hex($product, $attribute_name = 'pa_color')
{
$color_hex_values = [];
if ($product) {
$attributes = $product->get_attributes();
// Check if the specified attribute exists in the product
if (isset($attributes[$attribute_name])) {
$color_attribute = $attributes[$attribute_name];
if ($color_attribute->is_taxonomy()) {
// If the attribute is a taxonomy, get the terms and then fetch the color data
$terms = wc_get_product_terms($product->get_id(), $color_attribute->get_name(), array('fields' => 'all'));
foreach ($terms as $term) {
// Assuming color HEX is stored in term meta, replace 'color_hex' with the actual meta key
$color_hex = get_term_meta($term->term_id, 'product_attribute_color', true);
if ($color_hex) {
$color_hex_values = [
'color' => $term->name,
'hex' => $color_hex
];
}
}
}
}
}
return $color_hex_values;
}
function get_products_by_sku_with_color($sku)
{
global $wpdb;
if (str_contains($sku, '-')) {
$sku = substr($sku, 0, strrpos($sku, '-')) . '-';
$whereSku = "pm.meta_value LIKE '$sku%'";
} else {
$whereSku = "pm.meta_value = '$sku'";
}
$query = "
SELECT p.ID
FROM {$wpdb->posts} AS p
INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id
WHERE pm.meta_key = '_sku' AND $whereSku
AND p.post_type = 'product' AND p.post_status = 'publish'
";
$product_ids = $wpdb->get_col($wpdb->prepare($query));
$products_with_color = [];
foreach ($product_ids as $product_id) {
$product = wc_get_product($product_id);
$color = get_product_color_hex($product);
$products_with_color[] = [
'product_id' => $product_id,
'image_id' => $product->get_image_id(),
'permalink' => $product->get_permalink(),
'color' => $color['color'],
'hex' => $color['hex']
];
}
return $products_with_color;
}
function get_product_sizes($product_id)
{
$product = wc_get_product($product_id);
$product_sizes = [];
if ($product && $product->is_type('variable')) {
$variations = $product->get_children();
foreach ($variations as $variation_id) {
/**
* @var WC_Product $variation
*/
$variation = wc_get_product($variation_id);
if (!$variation) continue;
if (!empty($variation->get_attribute('pa_size'))) {
$size = $variation->get_attribute('pa_size');
$is_in_stock = $variation->get_stock_quantity() > 0 && $variation->is_in_stock();
$product_sizes[] = [
'title' => strtoupper($size),
'in_stock' => $is_in_stock,
'variation_id' => $variation_id,
'quantity' => $variation->get_stock_quantity(),
'is_on_sale' => $variation->is_on_sale(),
'sale_price' => $variation->get_sale_price(),
'regular_price' => $variation->get_regular_price()
];
}
}
}
usort($product_sizes, function ($a, $b) {
$size_order = ['XXS', 'XS', 'S', 'S/M', 'M', 'M/L', 'L', 'L/XL', 'XL'];
$pos_a = array_search($a['title'], $size_order);
$pos_b = array_search($b['title'], $size_order);
return $pos_a - $pos_b;
});
return $product_sizes;
}
//function register_custom_order_statuses()
//{
// $custom_statuses = array(
// 'wc-novij' => 'Новий',
// 'wc-pidtverdzheno' => 'Підтверджено',
// 'wc-na-vidpravku' => 'На відправку',
// 'wc-vidpravleno' => 'Відправлено',
// 'wc-ochikuye-nova-poshta' => 'Очікує (Нова Пошта)',
// 'wc-v-dorozi-nova-poshta' => 'В дорозі (Нова Пошта)',
// 'wc-pribuv-nova-poshta' => 'Прибув (Нова Пошта)',
// 'wc-otrimano-bez-pislyaplati-nova-poshta' => 'Отримано, без післяплати (Нова Пошта)',
// 'wc-otrimano-chekayemo-nova-poshta' => 'Отримано. Чекаємо ₴ (Нова Пошта)',
// 'wc-otrimano-otrimani-nova-poshta' => 'Отримано. ₴ отримані (Нова Пошта)',
// 'wc-vidmova-nova-poshta' => 'Відмова (Нова Пошта)',
// 'wc-zmineno-adresu-nova-poshta' => 'Змінено адресу (Нова Пошта)',
// 'wc-pripineno-zberigannya-nova-poshta' => 'Припинено зберігання (Нова Пошта)',
// 'wc-prodazh' => 'Продаж',
// 'wc-vidmova' => 'Відмова',
// 'wc-povernennya' => 'Повернення',
// 'wc-vidalenij' => 'Видалений'
// );
//
// foreach ($custom_statuses as $status_key => $status_label) {
// register_post_status($status_key, array(
// 'label' => $status_label,
// 'public' => true,
// 'exclude_from_search' => false,
// 'show_in_admin_all_list' => true,
// 'show_in_admin_status_list' => true,
// 'label_count' => _n_noop($status_label . ' <span class="count">(%s)</span>', $status_label . ' <span class="count">(%s)</span>')
// ));
// }
//}
//
//add_action('init', 'register_custom_order_statuses');
//
//function add_custom_order_statuses_to_wc($order_statuses)
//{
// $new_order_statuses = array();
// // Fetch globally defined custom statuses
// $custom_statuses = globally_defined_custom_order_statuses();
//
// foreach ($order_statuses as $key => $status) {
// $new_order_statuses[$key] = $status;
//
// // Insert custom statuses into the array
// if ('wc-processing' === $key) { // Choose where to insert the custom status
// foreach ($custom_statuses as $custom_key => $custom_status) {
// $new_order_statuses[$custom_key] = $custom_status;
// }
// }
// }
//
// return $new_order_statuses;
//}
//
//add_filter('wc_order_statuses', 'add_custom_order_statuses_to_wc');
//
//function globally_defined_custom_order_statuses()
//{
// $custom_statuses = array(
// 'wc-novij' => 'Новий',
// 'wc-pidtverdzheno' => 'Підтверджено',
// 'wc-na-vidpravku' => 'На відправку',
// 'wc-vidpravleno' => 'Відправлено',
// 'wc-ochikuye-nova-poshta' => 'Очікує (Нова Пошта)',
// 'wc-v-dorozi-nova-poshta' => 'В дорозі (Нова Пошта)',
// 'wc-pribuv-nova-poshta' => 'Прибув (Нова Пошта)',
// 'wc-otrimano-bez-pislyaplati-nova-poshta' => 'Отримано, без післяплати (Нова Пошта)',
// 'wc-otrimano-chekayemo-nova-poshta' => 'Отримано. Чекаємо ₴ (Нова Пошта)',
// 'wc-otrimano-otrimani-nova-poshta' => 'Отримано. ₴ отримані (Нова Пошта)',
// 'wc-vidmova-nova-poshta' => 'Відмова (Нова Пошта)',
// 'wc-zmineno-adresu-nova-poshta' => 'Змінено адресу (Нова Пошта)',
// 'wc-pripineno-zberigannya-nova-poshta' => 'Припинено зберігання (Нова Пошта)',
// 'wc-prodazh' => 'Продаж',
// 'wc-vidmova' => 'Відмова',
// 'wc-povernennya' => 'Повернення',
// 'wc-vidalenij' => 'Видалений'
// );
//
// return $custom_statuses;
//}
/**
* @TODO: remove
*/
add_action('wp_ajax_update_cart', 'update_cart_ajax');
add_action('wp_ajax_nopriv_update_cart', 'update_cart_ajax');
function update_cart_ajax()
{
$product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
$quantity = isset($_POST['quantity']) ? intval($_POST['quantity']) : 0;
if ($product_id > 0 && $quantity >= 0) {
$cart = WC()->cart;
$found = false;
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
if ($cart_item['variation_id'] == $product_id) {
$cart->set_quantity($cart_item_key, $quantity, false);
$found = $cart_item_key;
break;
}
}
if ($found) {
$cart->calculate_totals();
$_product = wc_get_product($product_id);
$cart_item = $cart->get_cart_item($found);
$line_total = $_product->get_price() * $cart_item['quantity'];
$cart_total = $cart->get_total('edit');
wp_send_json_success(array(
'quantity' => $quantity,
'price' => number_format($line_total, 2) . ' грн',
'total' => number_format($cart_total, 2) . ' грн'
)
);
} else {
wp_send_json_error(); // Product not found in cart
}
} else {
wp_send_json_error(); // No product ID provided or quantity is invalid
}
}
add_action('wp_ajax_delete_from_cart', 'delete_item_from_cart');
add_action('wp_ajax_nopriv_delete_from_cart', 'delete_item_from_cart');
/**
* @TODO: remove
*/
function delete_item_from_cart()
{
$product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
if ($product_id > 0) {
$cart = WC()->cart;
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
if ($cart_item['variation_id'] == $product_id) {
$cart->remove_cart_item($cart_item_key);
$cart->calculate_totals();
$cart_total = $cart->get_total('edit');
wp_send_json_success(
array(
'total' => number_format($cart_total, 2) . ' грн'
)
);
return;
}
}
wp_send_json_error(); // Product not found in cart
} else {
wp_send_json_error(); // No product ID provided
}
}
add_action('wp_ajax_apply_coupon', 'apply_coupon_ajax');
add_action('wp_ajax_nopriv_apply_coupon', 'apply_coupon_ajax');
/**
* @TODO: remove
*/
function apply_coupon_ajax()
{
if (!isset($_POST['coupon_code'])) {
wp_send_json_error(['message' => 'No coupon code provided']);
}
$cart = WC()->cart;
$coupon_code = sanitize_text_field($_POST['coupon_code']);
if ($cart->has_discount($coupon_code)) {
wp_send_json_error(['message' => 'Coupon has already been applied']);
}
if ($cart->apply_coupon($coupon_code)) {
$cart->calculate_totals();
$cart_total = $cart->get_total('edit');
wp_send_json_success(
array(
'message' => 'Промокод успішно застосовано',
'total' => number_format($cart_total, 2) . ' грн'
)
);
} else {
wp_send_json_error(['message' => 'Неправильний промокод']);
}
wp_die();
}
function success_theme_setup()
{
register_nav_menus(
array(
'main-menu' => __('Main Menu'),
'profile-menu' => __('Особистий кабінет'),
'information-menu' => __('Особистий кабінет - Інформація'),
'footer-information-menu' => __('Футер - Інформація'),
'footer-account-menu' => __('Футер - Особистий кабінет'),
'footer-additional-menu' => __('Футер - Додатково'),
'footer-policy' => __('Футер - Низ')
)
);
}
add_action('init', 'success_theme_setup');
function replace_more_with_html($content)
{
if (str_contains($content, '<p><!--more--></p>')) {
$content = str_replace('<p><!--more--></p>', '<!--more-->', $content);
}
if (str_contains($content, '<!--more-->')) {
$parts = explode('<!--more-->', $content);
if (count($parts) == 2) {
$replacement = '<div class="read-more">
<a href="">дізнатись більше</a>
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="10" viewBox="0 0 13 10" fill="none">
<path d="M7.28568 9L12 4.99998M12 4.99998L7.28568 1M12 4.99998L1 5.00013" stroke="black"
stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>';
$hidden_content = '<div class="hidden-text">' . $parts[1] . '</div>';
$content = $parts[0] . $hidden_content . $replacement;
}
}
if (str_contains($content, '<p></p>')) {
$content = str_replace('<p></p>', '', $content);
}
return $content;
}
function format_phone($phoneNumber)
{
// Define the pattern and replacement format
$pattern = '/(d{2})(d{3})(d{3})(d{2})(d{2})/';
$replacement = '+$1 $2 $3$4$5';
// Format the phone number using preg_replace
return preg_replace($pattern, $replacement, $phoneNumber);
}
if (!function_exists('success_woocommerce_form_field')) {
/**
* Outputs a checkout/address form field.
*
* @param string $key Key.
* @param mixed $args Arguments.
* @param string $value (default: null).
* @return string
*/
function success_woocommerce_form_field($key, $args, $value = null)
{
$defaults = array(
'type' => 'text',
'label' => '',
'description' => '',
'placeholder' => '',
'maxlength' => false,
'minlength' => false,
'required' => false,
'autocomplete' => false,
'id' => $key,
'class' => array(),
'label_class' => array(),
'input_class' => array(),
'return' => false,
'error' => array(),
'options' => array(),
'custom_attributes' => array(),
'validate' => array(),
'default' => '',
'autofocus' => '',
'priority' => '',
'unchecked_value' => null,
'checked_value' => '1',
);
$args = wp_parse_args($args, $defaults);
$args = apply_filters('woocommerce_form_field_args', $args, $key, $value);
if (is_string($args['class'])) {
$args['class'] = array($args['class']);
}
if ($args['required']) {
$args['class'][] = 'validate-required';
$required = ' <abbr class="required" title="' . esc_attr__('required', 'woocommerce') . '">*</abbr>';
} else {
$required = ' <span class="optional">(' . esc_html__('optional', 'woocommerce') . ')</span>';
}
if (is_string($args['label_class'])) {
$args['label_class'] = array($args['label_class']);
}
if (is_null($value)) {
$value = $args['default'];
}
// Custom attribute handling.
$custom_attributes = array();
$args['custom_attributes'] = array_filter((array)$args['custom_attributes'], 'strlen');
if ($args['maxlength']) {
$args['custom_attributes']['maxlength'] = absint($args['maxlength']);
}
if ($args['minlength']) {
$args['custom_attributes']['minlength'] = absint($args['minlength']);
}
if (!empty($args['autocomplete'])) {
$args['custom_attributes']['autocomplete'] = $args['autocomplete'];
}
if (true === $args['autofocus']) {
$args['custom_attributes']['autofocus'] = 'autofocus';
}
if ($args['description']) {
$args['custom_attributes']['aria-describedby'] = $args['id'] . '-description';
}
if (!empty($args['custom_attributes']) && is_array($args['custom_attributes'])) {
foreach ($args['custom_attributes'] as $attribute => $attribute_value) {
$custom_attributes[] = esc_attr($attribute) . '="' . esc_attr($attribute_value) . '"';
}
}
if (!empty($args['validate'])) {
foreach ($args['validate'] as $validate) {
$args['class'][] = 'validate-' . $validate;
}
}
$field = '';
$label_id = $args['id'];
$sort = $args['priority'] ?: '';
$has_value_class = $value ? ' has-value' : '';
$has_error_class = !empty($args['error']) ? ' has-error' : '';
$field_container = '<div class="form-group success-input-group' . $has_value_class . $has_error_class . '" id="%2$s" data-priority="' . esc_attr($sort) . '">%3$s</div>';
switch ($args['type']) {
case 'textarea':
$field .= '<textarea name="' . esc_attr($key) . '" class="form-control ' . esc_attr(implode(' ', $args['input_class'])) . '" id="' . esc_attr($args['id']) . '" placeholder="' . esc_attr($args['placeholder']) . '" ' . (empty($args['custom_attributes']['rows']) ? ' rows="2"' : '') . (empty($args['custom_attributes']['cols']) ? ' cols="5"' : '') . implode(' ', $custom_attributes) . '>' . esc_textarea($value) . '</textarea>';
break;
case 'checkbox':
$field = '<label class="checkbox ' . esc_attr(implode(' ', $args['label_class'])) . '" ' . implode(' ', $custom_attributes) . '>';
// Output a hidden field so a value is POSTed if the box is not checked.
if (!is_null($args['unchecked_value'])) {
$field .= sprintf('<input type="hidden" name="%1$s" value="%2$s" />', esc_attr($key), esc_attr($args['unchecked_value']));
}
$field .= sprintf(
'<input type="checkbox" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s /> %6$s',
esc_attr($key),
esc_attr($args['id']),
esc_attr($args['checked_value']),
esc_attr('input-checkbox ' . implode(' ', $args['input_class'])),
checked($value, $args['checked_value'], false),
wp_kses_post($args['label'])
);
$field .= $required . '</label>';
break;
case 'text':
case 'password':
case 'datetime':
case 'datetime-local':
case 'date':
case 'month':
case 'time':
case 'week':
case 'number':
case 'email':
case 'url':
case 'tel':
$field .= '<input type="' . esc_attr($args['type']) . '" class="form-control ' . esc_attr(implode(' ', $args['input_class'])) . '" name="' . esc_attr($key) . '" id="' . esc_attr($args['id']) . '" placeholder="' . esc_attr($args['placeholder']) . '" value="' . esc_attr($value) . '" ' . implode(' ', $custom_attributes) . ' />';
break;
case 'hidden':
$field .= '<input type="' . esc_attr($args['type']) . '" class="input-hidden ' . esc_attr(implode(' ', $args['input_class'])) . '" name="' . esc_attr($key) . '" id="' . esc_attr($args['id']) . '" value="' . esc_attr($value) . '" ' . implode(' ', $custom_attributes) . ' />';
break;
case 'select':
$field = '';
$options = '';
if (!empty($args['options'])) {
foreach ($args['options'] as $option_key => $option_text) {
if ('' === $option_key) {
// If we have a blank option, select2 needs a placeholder.
if (empty($args['placeholder'])) {
$args['placeholder'] = $option_text ? $option_text : __('Choose an option', 'woocommerce');
}
$custom_attributes[] = 'data-allow_clear="true"';
}
$options .= '<option value="' . esc_attr($option_key) . '" ' . selected($value, $option_key, false) . '>' . esc_html($option_text) . '</option>';
}
$field .= '<select name="' . esc_attr($key) . '" id="' . esc_attr($args['id']) . '" class="select ' . esc_attr(implode(' ', $args['input_class'])) . '" ' . implode(' ', $custom_attributes) . ' data-placeholder="' . esc_attr($args['placeholder']) . '">
' . $options . '
</select>';
}
break;
case 'radio':
$label_id .= '_' . current(array_keys($args['options']));
if (!empty($args['options'])) {
foreach ($args['options'] as $option_key => $option_text) {
$field .= '<input type="radio" class="input-radio ' . esc_attr(implode(' ', $args['input_class'])) . '" value="' . esc_attr($option_key) . '" name="' . esc_attr($key) . '" ' . implode(' ', $custom_attributes) . ' id="' . esc_attr($args['id']) . '_' . esc_attr($option_key) . '"' . checked($value, $option_key, false) . ' />';
$field .= '<label for="' . esc_attr($args['id']) . '_' . esc_attr($option_key) . '" class="radio ' . implode(' ', $args['label_class']) . '">' . esc_html($option_text) . '</label>';
}
}
break;
}
if (!empty($field)) {
$field_html = $field;
if ($args['label'] && 'checkbox' !== $args['type']) {
$field_html .= '<label for="' . esc_attr($label_id) . '" class="' . esc_attr(implode(' ', $args['label_class'])) . '">' . wp_kses_post($args['label']) . $required . '</label>';
}
if ($args['error']) {
$field_html .= '<div class="invalid-feedback">' . esc_attr($args['error']) . '</div>';
}
$container_class = esc_attr(implode(' ', $args['class']));
$container_id = esc_attr($args['id']) . '_field';
$field = sprintf($field_container, $container_class, $container_id, $field_html);
}
/**
* General filter on form fields.
*
* @since 3.4.0
*/
$field = apply_filters('woocommerce_form_field', $field, $key, $args, $value);
if ($args['return']) {
return $field;
} else {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $field;
}
}
}
/**
* @TODO: remove
*/
function custom_catalog_pagination_rewrite()
{
add_rewrite_rule('catalog/page/([0-9]{1,})/?$', 'index.php?pagename=catalog&paged=$matches[1]', 'top');
}
add_action('init', 'custom_catalog_pagination_rewrite');
//add_action('wp_footer', function () {
// global $wp_rewrite;
// echo '<pre>' . print_r($wp_rewrite->wp_rewrite_rules(), true) . '</pre>';
//});
add_filter('template_include', 'use_catalog_template_for_product_category', 99);
function use_catalog_template_for_product_category($template)
{
if (is_tax('product_cat')) { // Checks if on a product category page
$category_template = locate_template('page-catalog.php');
if ($category_template) {
return $category_template;
}
}
return $template;
}
/**
* @TODO: remove
*/
function get_min_max_product_prices($term_id = null)
{
global $wpdb; // Access to the WordPress database.
// Base SQL query
$sql = "
SELECT MIN(meta_value + 0.0) AS min_price, MAX(meta_value + 0.0) AS max_price
FROM {$wpdb->postmeta}
INNER JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id";
if (!is_null($term_id)) {
$sql .= "
INNER JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id
INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_taxonomy}.term_taxonomy_id = {$wpdb->term_relationships}.term_taxonomy_id
AND {$wpdb->term_taxonomy}.taxonomy = 'product_cat'
AND {$wpdb->term_taxonomy}.term_id = %d
";
$sql = $wpdb->prepare($sql, $term_id);
}
$sql .= "
WHERE meta_key = '_price'
AND {$wpdb->posts}.post_status = 'publish'
";
$prices = $wpdb->get_row($sql);
if (!is_null($prices)) {
// Return an associative array with min and max prices
return ['min_price' => $prices->min_price, 'max_price' => $prices->max_price];
} else {
// Return null if no prices are found
return null;
}
}
add_filter('tiny_mce_before_init', 'my_switch_tinymce_p_br');
function my_switch_tinymce_p_br($settings)
{
$settings['wpautop'] = false;
$settings['force_br_newlines'] = TRUE;
$settings['force_p_newlines'] = FALSE;
return $settings;
}
add_action('template_redirect', 'update_recently_viewed_products_cookie');
function update_recently_viewed_products_cookie()
{
if (is_singular('product')) {
global $post;
$viewed_products = array();
if (!empty($_COOKIE['woocommerce_recently_viewed'])) {
$viewed_products = explode('|', $_COOKIE['woocommerce_recently_viewed']);
}
if (($key = array_search($post->ID, $viewed_products)) !== false) {
unset($viewed_products[$key]);
}
array_unshift($viewed_products, $post->ID);
$viewed_products = array_slice($viewed_products, 0, 12);
// Set the cookie again with updated array
$cookie_value = implode('|', $viewed_products);
setcookie('woocommerce_recently_viewed', $cookie_value, time() + 3600 * 24 * 30, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
}
}
function wc_get_viewed_products()
{
$viewed_products = array();
if (isset($_COOKIE['woocommerce_recently_viewed'])) {
$cookie_value = $_COOKIE['woocommerce_recently_viewed'];
$viewed_products = array_reverse(array_filter(array_map('absint', explode('|', $cookie_value))));
}
return $viewed_products;
}
add_filter('woocommerce_product_data_store_cpt_get_products_query', 'handle_price_range_query_var', 10, 2);
function handle_price_range_query_var($query, $query_vars)
{
if (!empty($query_vars['price_range'])) {
$price_range = esc_attr($query_vars['price_range']);
if (is_array($price_range) && count($price_range) == 2) {
$args['meta_query'][] = array(
'key' => '_price',
'value' => array(reset($price_range), end($price_range)),
'compare' => 'BETWEEN',
'type' => 'NUMERIC'
);
$query['orderby'] = 'meta_value_num'; // sort by price
$query['order'] = 'ASC'; // In ascending order
}
}
return $query;
}
/**
* Fetches instock and outofstock items separately the merge into a single WP_query
* to sort instock items first
*
* @param $args
* @param $items_per_page
* @param $page
* @return WP_Query | false
*/
function custom_query_outofstock_last($args = array(), $items_per_page = 10, $page = null)
{
global $wpdb;
// Set the default page if not provided
if (null === $page) {
$page = max(1, get_query_var('paged'));
}
$only_sale = !empty($args['only_sale']);
$args_in_stock = array_merge(
$args,
array(
'posts_per_page' => -1,
'meta_query' => array_merge(array(
'relation' => 'AND',
array(
'key' => '_stock_status',
'value' => 'instock',
'compare' => '=',
'type' => 'STRING',
),
), $args['meta_query']),
'fields' => 'ids',
)
);
$query_in_stock = new WP_Query($args_in_stock);
$in_stock_ids = $query_in_stock->posts;
// Query for out-of-stock items
$args_out_of_stock = array_merge(
$args,
array(
'meta_query' => array_merge(array(
'relation' => 'AND',
array(
'key' => '_stock_status',
'value' => 'outofstock',
'compare' => '=',
'type' => 'STRING',
),
), $args['meta_query']),
'fields' => 'ids',
)
);
$query_out_of_stock = new WP_Query($args_out_of_stock);
$out_of_stock_ids = $query_out_of_stock->posts;
$merged_post_ids = array_merge($in_stock_ids, $out_of_stock_ids);
if (empty($merged_post_ids)) {
return false;
}
// Convert the IDs to a comma-separated string
$post_ids_str = implode(',', $merged_post_ids);
$whereSaleSql = '';
if ($only_sale) {
$whereSaleSql = "AND p.ID IN (SELECT DISTINCT post_parent FROM {$wpdb->posts} WHERE ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE (wp_postmeta.meta_key = '_sale_price' AND CAST(wp_postmeta.meta_value AS SIGNED) > '0') ))";
}
// Construct the SQL query
$sql = "SELECT p.ID
FROM {$wpdb->posts} p
WHERE p.ID IN ($post_ids_str) ${whereSaleSql}
ORDER BY FIELD(p.ID, $post_ids_str)";
// Execute the query
$post_ids = $wpdb->get_col($sql);
// Query the posts based on the retrieved post IDs
$args_merged = array(
'post__in' => $post_ids,
'orderby' => 'post__in',
'paginate' => true,
'paged' => $page,
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => $items_per_page,
);
$query_merged = new WP_Query($args_merged);
return $query_merged;
}
function find_product_in_cart(int $product_id): bool
{
foreach (WC()->cart->get_cart() as $values) {
$cart_product = $values['data'];
if ($product_id == $cart_product->id) {
return true;
}
}
return false;
}
function track_view_item_list_event()
{
if (is_shop() || is_product_category()) {
?>
<script>
jQuery(document).ready(function ($) {
var products = [];
$('#catalog-products .product-card').each(function () {
var product = {
'id': $(this).data('product-id'),
'name': $(this).find('.product-title').text().trim(),
'price': $(this).find('.current-price').text().trim()
};
products.push(product);
});
dataLayer.push({
'event': 'view_item_list',
'ecommerce': {
'impressions': products
}
});
});
</script>
<?php
}
}
add_action('wp_footer', 'track_view_item_list_event');
/**
* Change the sublabels for the Password field.
*
* @link https://wpforms.com/developers/how-to-change-the-password-field-sublabels/
*/
function wpf_dev_password_field_properties($properties, $field, $form_data)
{
// Change sublabel values on the primary password field
$properties['inputs']['primary']['sublabel']['value'] = __('Password', 'woocommerce');
// Change the sublabel values on the secondary password field
$properties['inputs']['secondary']['sublabel']['value'] = __('Підтвердження паролю', 'woocommerce');
return $properties;
}
add_filter('wpforms_field_properties_password', 'wpf_dev_password_field_properties', 10, 3);
function fetch_size_chart($atts)
{
$atts = shortcode_atts(array(
'category_ids' => '',
), $atts, 'size_chart');
$category_ids = explode(',', $atts['category_ids']);
if (empty($category_ids)) {
return 'No categories found for this product.';
}
global $wpdb;
// Sanitize the category IDs
$category_ids = array_map('intval', $category_ids);
$query = "
SELECT p.ID, p.post_title, pm.meta_value as table_data, pm2.meta_value as product_data
FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = 'zpsc_table_data'
LEFT JOIN {$wpdb->postmeta} pm2 ON p.ID = pm2.post_id AND pm2.meta_key = 'zpsc_product'
WHERE p.post_type = 'zpsc-size-chart'
AND p.post_status = 'publish'
";
$results = $wpdb->get_results($query);
$filtered_results = array_filter($results, function ($result) use ($category_ids) {
$product_categories = maybe_unserialize($result->product_data);
if (is_array($product_categories)) {
foreach ($product_categories as $category_id) {
if (in_array(intval($category_id), $category_ids)) {
return true;
}
}
}
return false;
});
if (empty($filtered_results)) {
return 'No size charts found for the specified category IDs.';
}
$output = '<div class="size-charts">';
foreach ($filtered_results as $result) {
$table_data = json_decode($result->table_data, true);
if (is_array($table_data)) {
$output .= '<h5>' . $result->post_title . '</h5>';
$output .= '<table class="table">';
$output .= '<thead><tr>';
foreach ($table_data[0] as $header_cell) {
$output .= '<th>' . esc_html($header_cell) . '</th>';
}
$output .= '</tr></thead><tbody>';
for ($i = 1; $i < count($table_data); $i++) {
$output .= '<tr>';
foreach ($table_data[$i] as $cell) {
$output .= '<td>' . esc_html($cell) . '</td>';
}
$output .= '</tr>';
}
$output .= '</tbody></table>';
}
}
$output .= '</div>';
return $output;
}
add_shortcode('size_chart', 'fetch_size_chart');
add_action('wp_ajax_fetch_product_template', 'fetch_product_template');
add_action('wp_ajax_nopriv_fetch_product_template', 'fetch_product_template');
function fetch_product_template()
{
if (!isset($_POST['product_id']) || !is_numeric($_POST['product_id'])) {
wp_send_json_error('Invalid product ID');
wp_die();
}
$product_id = intval($_POST['product_id']);
$product = wc_get_product($product_id);
if (!$product) {
wp_send_json_error('Product not found');
wp_die();
}
// Make the product data globally accessible
global $product_data;
$product_data = $product;
ob_start();
wc_get_template_part('partials/cart/cart-item');
$product_html = ob_get_clean();
wp_send_json_success([
'product_html' => $product_html,
'product_name' => $product->get_name(),
'product_sku' => $product->get_sku()
]);
wp_die();
}
function get_stores_availability($atts)
{
// Extract shortcode attributes
$atts = shortcode_atts(array(
'product_id' => 0,
), $atts, 'stores_availability');
$product_id = intval($atts['product_id']);
if (!$product_id) {
return 'Invalid product ID.';
}
// Fetch the _stores_availability meta value
$stores_availability = get_post_meta($product_id, '_stores_availability', true);
$stores_availability = (json_decode($stores_availability, true) ?? []);
// Fetch all stores
$args = array(
'post_type' => 'stores',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'title'
);
$stores_query = new WP_Query($args);
if (!$stores_query->have_posts()) {
return 'No stores found.';
}
// Map store IDs to availability data
$availability_map = array();
foreach ($stores_availability as $store_data) {
$availability_map[$store_data['store_id']] = $store_data;
}
// Extract all size keys
$size_keys = array();
foreach ($availability_map as $store_data) {
$size_keys = array_merge($size_keys, array_keys($store_data));
}
$size_keys = array_unique($size_keys);
usort($size_keys, function ($a, $b) {
$size_order = ['XXS', 'XS', 'S', 'S/M', 'M', 'M/L', 'L', 'L/XL', 'XL'];
$pos_a = array_search($a, $size_order);
$pos_b = array_search($b, $size_order);
return $pos_a - $pos_b;
});
// Remove 'store_id' from size keys
if (($key = array_search('store_id', $size_keys)) !== false) {
unset($size_keys[$key]);
}
// Generate output table
$output = '<table class="table" id="table-availability"><tbody>';
while ($stores_query->have_posts()) {
$stores_query->the_post();
$store_id = get_the_ID();
$store_address = get_post_meta($store_id, 'store-address', true);
if (!$store_address) {
$store_address = '';
}
$is_in_stock = isset($availability_map[$store_id]);
$status_badge = $is_in_stock ? '<span class="badge bg-success">В наявності</span>' : '<span class="badge bg-secondary">Немає в наявності</span>';
$output .= '<tr>';
$output .= '<td><p class="store-title">' . esc_html(get_the_title()) . '</p>';
$output .= '<small class="store-address">' . esc_html($store_address) . '</small>';
if (!empty($availability_map[$store_id])) {
$output .= '<p class="available-sizes">';
foreach ($size_keys as $size_key) {
if (isset($availability_map[$store_id][$size_key])) {
$output .= '<span class="available-size">' . $size_key . '</span>';
}
}
}
$output .= '</p></td>';
$output .= '<td class="text-right">' . $status_badge . '</td>';
$output .= '</tr>';
}
wp_reset_postdata();
$output .= '</tbody></table>';
return $output;
}
add_shortcode('stores_availability', 'get_stores_availability');
function get_products_by_title_or_sku($search_term)
{
global $wpdb;
// Sanitize the search term for use in a LIKE query
$search_term = '%' . $wpdb->esc_like($search_term) . '%';
// Construct the raw SQL query
$query = $wpdb->prepare(
"SELECT DISTINCT p.ID
FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND (p.post_title OR (pm.meta_key = '_sku' AND pm.meta_value LIKE %s))",
$search_term, $search_term, $search_term, $search_term
);
// Execute the query and get the results
$products = $wpdb->get_col($query);
// Return the array of posts or an empty array
return !empty($products) ? $products : [];
}
I have added comments to explain the purpose and functionality of each section of the code. These comments should help you understand the code better and make any necessary modifications or customizations.