finction.php

Pasted Oct 11, 2026, 8:08 AM1 file1,770 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/finction
untitled
/**
 * WooCommerce - سیستم فروش وزنی / بسته بندی
 *
 * نسخه اصلاح شده
 *
 * امکانات:
 * - تنظیم نوع فروش در دسته بندی
 * - تنظیم نوع فروش در هر محصول
 * - اولویت تنظیم محصول نسبت به دسته
 * - حالت وزنی / بسته بندی
 * - حداقل وزن
 * - گام افزایش
 * - بدون حداکثر وزن
 * - انتخاب گرم / کیلوگرم
 * - ورود مستقیم وزن
 * - دکمه + و -
 * - انتخاب تعداد
 * - محاسبه قیمت بر اساس هر کیلوگرم
 * - گرد کردن قیمت به نزدیک ترین 1000 تومان
 * - جلوگیری از تغییر قیمت سایر ردیف های Cart
 */


/* =========================================================
 * 1. تنظیمات پیش فرض
 * ========================================================= */

function mw_weight_defaults() {

	return array(
		'min'  => 100,
		'step' => 100,
	);
}


/* =========================================================
 * 2. گرفتن تنظیمات دسته بندی
 * ========================================================= */

function mw_get_category_weight_settings( $product_id ) {

	$defaults = mw_weight_defaults();

	$categories = wp_get_post_terms(
		$product_id,
		'product_cat',
		array(
			'fields' => 'ids',
		)
	);

	if (
		empty( $categories ) ||
		is_wp_error( $categories )
	) {

		return array(
			'enabled' => false,
			'min'     => $defaults['min'],
			'step'    => $defaults['step'],
		);
	}


	foreach ( $categories as $category_id ) {

		$enabled = get_term_meta(
			$category_id,
			'_mw_category_weight_enabled',
			true
		);

		if ( 'yes' !== $enabled ) {
			continue;
		}


		$min = get_term_meta(
			$category_id,
			'_mw_category_weight_min',
			true
		);

		$step = get_term_meta(
			$category_id,
			'_mw_category_weight_step',
			true
		);


		$min  = absint( $min );
		$step = absint( $step );


		if ( $min < 1 ) {
			$min = $defaults['min'];
		}


		if ( $step < 1 ) {
			$step = $defaults['step'];
		}


		return array(
			'enabled' => true,
			'min'     => $min,
			'step'    => $step,
		);
	}


	return array(
		'enabled' => false,
		'min'     => $defaults['min'],
		'step'    => $defaults['step'],
	);
}


/* =========================================================
 * 3. نوع فروش محصول
 *
 * category = استفاده از تنظیم دسته
 * weight   = وزنی
 * package  = بسته بندی
 * ========================================================= */

function mw_get_product_sale_type( $product_id ) {

	$product_type = get_post_meta(
		$product_id,
		'_mw_product_sale_type',
		true
	);


	/*
	 * اگر محصول صریحاً تنظیم شده باشد
	 */

	if (
		in_array(
			$product_type,
			array(
				'weight',
				'package',
			),
			true
		)
	) {

		return $product_type;
	}


	/*
	 * در غیر این صورت از دسته بندی استفاده کن
	 */

	$category_settings =
		mw_get_category_weight_settings(
			$product_id
		);


	if ( $category_settings['enabled'] ) {
		return 'weight';
	}


	return 'package';
}


/* =========================================================
 * 4. تنظیمات نهایی وزن محصول
 * ========================================================= */

function mw_get_weight_settings( $product_id ) {

	$defaults = mw_weight_defaults();


	/*
	 * تنظیمات دسته
	 */

	$category_settings =
		mw_get_category_weight_settings(
			$product_id
		);


	$min  = $category_settings['min'];
	$step = $category_settings['step'];


	/*
	 * تنظیم اختصاصی محصول
	 */

	$product_min = get_post_meta(
		$product_id,
		'_mw_weight_min',
		true
	);

	$product_step = get_post_meta(
		$product_id,
		'_mw_weight_step',
		true
	);


	if ( '' !== $product_min ) {

		$product_min = absint(
			$product_min
		);

		if ( $product_min > 0 ) {
			$min = $product_min;
		}
	}


	if ( '' !== $product_step ) {

		$product_step = absint(
			$product_step
		);

		if ( $product_step > 0 ) {
			$step = $product_step;
		}
	}


	if ( $min < 1 ) {
		$min = $defaults['min'];
	}


	if ( $step < 1 ) {
		$step = $defaults['step'];
	}


	return array(
		'min'  => $min,
		'step' => $step,
	);
}

/* =========================================================
 * 5. گرد کردن قیمت
 * ========================================================= */
/*
function mw_round_weight_price( $price ) {

	$price = (float) $price;


	if ( $price <= 0 ) {
		return 0;
	}


	return round(
		$price / 1000
	) * 1000;
}

*/

/* =========================================================
 * 6. تبدیل گرم به متن
 * ========================================================= */

function mw_format_weight_text( $weight ) {

	$weight = absint( $weight );


	if ( $weight < 1000 ) {

		return number_format_i18n(
			$weight
		) . ' گرم';
	}


	$kg = floor(
		$weight / 1000
	);

	$gram = $weight % 1000;


	if ( 0 === $gram ) {

		return number_format_i18n(
			$kg
		) . ' کیلوگرم';
	}


	return number_format_i18n(
		$kg
	)
	. ' کیلوگرم و '
	. number_format_i18n(
		$gram
	)
	. ' گرم';
}


/* =========================================================
 * 7. فیلدهای دسته بندی
 * ========================================================= */

add_action(
	'product_cat_add_form_fields',
	'mw_category_weight_add_fields'
);

function mw_category_weight_add_fields() {

	?>

	<div class="form-field">

		<label for="mw_category_weight_enabled">
			فروش محصولات این دسته بر اساس وزن
		</label>

		<input
			type="checkbox"
			name="mw_category_weight_enabled"
			id="mw_category_weight_enabled"
			value="yes"
		>

		<p class="description">
			اگر فعال باشد، محصولاتی که روی «پیش‌فرض دسته‌بندی» هستند به صورت وزنی فروخته می‌شوند.
		</p>

	</div>


	<div class="form-field">

		<label for="mw_category_weight_min">
			حداقل وزن (گرم)
		</label>

		<input
			type="number"
			name="mw_category_weight_min"
			id="mw_category_weight_min"
			value="100"
			min="1"
			step="1"
		>

		<p class="description">
			مثلاً 100 گرم.
		</p>

	</div>


	<div class="form-field">

		<label for="mw_category_weight_step">
			گام افزایش (گرم)
		</label>

		<input
			type="number"
			name="mw_category_weight_step"
			id="mw_category_weight_step"
			value="100"
			min="1"
			step="1"
		>

		<p class="description">
			مثلاً 100 یعنی 100، 200، 300، 400 و ...
		</p>

	</div>

	<?php
}


/* =========================================================
 * 8. ویرایش دسته بندی
 * ========================================================= */

add_action(
	'product_cat_edit_form_fields',
	'mw_category_weight_edit_fields'
);

function mw_category_weight_edit_fields( $term ) {

	$enabled = get_term_meta(
		$term->term_id,
		'_mw_category_weight_enabled',
		true
	);

	$min = get_term_meta(
		$term->term_id,
		'_mw_category_weight_min',
		true
	);

	$step = get_term_meta(
		$term->term_id,
		'_mw_category_weight_step',
		true
	);


	if ( '' === $min ) {
		$min = 100;
	}


	if ( '' === $step ) {
		$step = 100;
	}

	?>

	<tr class="form-field">

		<th scope="row">
			<label for="mw_category_weight_enabled">
				فروش بر اساس وزن
			</label>
		</th>

		<td>

			<input
				type="checkbox"
				name="mw_category_weight_enabled"
				id="mw_category_weight_enabled"
				value="yes"
				<?php checked(
					$enabled,
					'yes'
				); ?>
			>

			<p class="description">
				محصولات دارای «پیش‌فرض دسته‌بندی» در این دسته وزنی می‌شوند.
			</p>

		</td>

	</tr>


	<tr class="form-field">

		<th scope="row">
			<label for="mw_category_weight_min">
				حداقل وزن (گرم)
			</label>
		</th>

		<td>

			<input
				type="number"
				name="mw_category_weight_min"
				id="mw_category_weight_min"
				value="<?php echo esc_attr( $min ); ?>"
				min="1"
				step="1"
			>

			<p class="description">
				مثلاً 100 گرم.
			</p>

		</td>

	</tr>


	<tr class="form-field">

		<th scope="row">
			<label for="mw_category_weight_step">
				گام افزایش (گرم)
			</label>
		</th>

		<td>

			<input
				type="number"
				name="mw_category_weight_step"
				id="mw_category_weight_step"
				value="<?php echo esc_attr( $step ); ?>"
				min="1"
				step="1"
			>

			<p class="description">
				مثلاً 100 یعنی 100، 200، 300، 400 و ...
			</p>

		</td>

	</tr>

	<?php
}


/* =========================================================
 * 9. ذخیره دسته بندی
 * ========================================================= */

add_action(
	'created_product_cat',
	'mw_save_category_weight_fields'
);

add_action(
	'edited_product_cat',
	'mw_save_category_weight_fields'
);

function mw_save_category_weight_fields( $term_id ) {

	$enabled = isset(
		$_POST['mw_category_weight_enabled']
	)
		? 'yes'
		: 'no';


	update_term_meta(
		$term_id,
		'_mw_category_weight_enabled',
		$enabled
	);


	if (
		isset(
			$_POST['mw_category_weight_min']
		)
	) {

		update_term_meta(
			$term_id,
			'_mw_category_weight_min',
			absint(
				$_POST['mw_category_weight_min']
			)
		);
	}


	if (
		isset(
			$_POST['mw_category_weight_step']
		)
	) {

		update_term_meta(
			$term_id,
			'_mw_category_weight_step',
			absint(
				$_POST['mw_category_weight_step']
			)
		);
	}
}


/* =========================================================
 * 10. فیلدهای محصول
 * ========================================================= */

add_action(
	'woocommerce_product_options_general_product_data',
	'mw_product_sale_type_fields'
);

function mw_product_sale_type_fields() {

	echo '<div class="options_group">';


	woocommerce_wp_select(
		array(
			'id'          => '_mw_product_sale_type',
			'label'       => 'نوع فروش',
			'description' => 'نوع فروش این محصول را مشخص کنید.',
			'desc_tip'    => true,
			'options'     => array(
				'category' => 'پیش‌فرض دسته‌بندی',
				'weight'   => 'وزنی',
				'package'  => 'بسته‌بندی / تعدادی',
			),
		)
	);


	woocommerce_wp_text_input(
		array(
			'id'                => '_mw_weight_min',
			'label'             => 'حداقل وزن (گرم)',
			'type'              => 'number',
			'description'       => 'اگر خالی باشد از دسته‌بندی استفاده می‌شود.',
			'desc_tip'          => true,
			'custom_attributes' => array(
				'min'  => '1',
				'step' => '1',
			),
		)
	);


	woocommerce_wp_text_input(
		array(
			'id'                => '_mw_weight_step',
			'label'             => 'گام افزایش (گرم)',
			'type'              => 'number',
			'description'       => 'اگر خالی باشد از دسته‌بندی استفاده می‌شود.',
			'desc_tip'          => true,
			'custom_attributes' => array(
				'min'  => '1',
				'step' => '1',
			),
		)
	);


	echo '</div>';
}


/* =========================================================
 * 11. ذخیره تنظیمات محصول
 * ========================================================= */

add_action(
	'woocommerce_process_product_meta',
	'mw_save_product_sale_type_fields'
);

function mw_save_product_sale_type_fields( $product_id ) {

	$type = isset(
		$_POST['_mw_product_sale_type']
	)
		? sanitize_text_field(
			wp_unslash(
				$_POST['_mw_product_sale_type']
			)
		)
		: 'category';


	if (
		! in_array(
			$type,
			array(
				'category',
				'weight',
				'package',
			),
			true
		)
	) {

		$type = 'category';
	}


	update_post_meta(
		$product_id,
		'_mw_product_sale_type',
		$type
	);


	/*
	 * حداقل وزن
	 */

	if (
		isset(
			$_POST['_mw_weight_min']
		)
	) {

		$value = absint(
			$_POST['_mw_weight_min']
		);


		if ( $value > 0 ) {

			update_post_meta(
				$product_id,
				'_mw_weight_min',
				$value
			);

		} else {

			delete_post_meta(
				$product_id,
				'_mw_weight_min'
			);
		}
	}


	/*
	 * گام
	 */

	if (
		isset(
			$_POST['_mw_weight_step']
		)
	) {

		$value = absint(
			$_POST['_mw_weight_step']
		);


		if ( $value > 0 ) {

			update_post_meta(
				$product_id,
				'_mw_weight_step',
				$value
			);

		} else {

			delete_post_meta(
				$product_id,
				'_mw_weight_step'
			);
		}
	}
}


/* =========================================================
 * 12. نمایش انتخاب وزن
 * ========================================================= */

add_action(
	'woocommerce_before_add_to_cart_button',
	'mw_weight_selector'
);

function mw_weight_selector() {

	global $product;

	if (
		! $product ||
		! is_a(
			$product,
			'WC_Product'
		)
	) {
		return;
	}


	$product_id = $product->get_id();


	if (
		'weight' !==
		mw_get_product_sale_type(
			$product_id
		)
	) {
		return;
	}


	$settings =
		mw_get_weight_settings(
			$product_id
		);


	$min  = $settings['min'];
	$step = $settings['step'];


	/*
	 * قیمت هر کیلوگرم
	 *
	 * فقط برای نمایش اولیه JS
	 */

	$base_price =
		(float)
		$product->get_price();


	if ( $base_price <= 0 ) {
		return;
	}

	?>

	<div
		class="mw-weight-box"
		data-base-price="<?php echo esc_attr( $base_price ); ?>"
		data-min="<?php echo esc_attr( $min ); ?>"
		data-step="<?php echo esc_attr( $step ); ?>"
	>

		<div class="mw-weight-heading">
			<span>وزن مورد نظر</span>
		</div>


		<div class="mw-unit-switch">

			<button
				type="button"
				class="mw-unit-btn active"
				data-unit="gram"
			>
				گرم
			</button>

			<button
				type="button"
				class="mw-unit-btn"
				data-unit="kg"
			>
				کیلوگرم
			</button>

		</div>


		<div class="mw-weight-control">

			<button
				type="button"
				class="mw-weight-plus"
				aria-label="افزایش وزن"
			>
				+
			</button>


			<div class="mw-weight-input-box">

				<input
					type="number"
					class="mw-weight-input"
					value="<?php echo esc_attr( $min ); ?>"
					min="<?php echo esc_attr( $min ); ?>"
					step="<?php echo esc_attr( $step ); ?>"
					inputmode="numeric"
					autocomplete="off"
				>

				<span class="mw-input-unit">
					گرم
				</span>

			</div>


			<button
				type="button"
				class="mw-weight-minus"
				aria-label="کاهش وزن"
			>
				−
			</button>

		</div>


		<div class="mw-weight-readable"></div>

		<div class="mw-weight-price"></div>


		<input
			type="hidden"
			name="mw_selected_weight"
			class="mw-selected-weight"
			value="<?php echo esc_attr( $min ); ?>"
		>

	</div>



	<script>

	document.addEventListener(
		'DOMContentLoaded',
		function () {

			const box =
				document.querySelector(
					'.mw-weight-box'
				);


			if ( ! box ) {
				return;
			}


			const input =
				box.querySelector(
					'.mw-weight-input'
				);


			const hiddenInput =
				box.querySelector(
					'.mw-selected-weight'
				);


			const plus =
				box.querySelector(
					'.mw-weight-plus'
				);


			const minus =
				box.querySelector(
					'.mw-weight-minus'
				);


			const priceBox =
				box.querySelector(
					'.mw-weight-price'
				);


			const readableBox =
				box.querySelector(
					'.mw-weight-readable'
				);


			const inputUnit =
				box.querySelector(
					'.mw-input-unit'
				);


			const unitButtons =
				box.querySelectorAll(
					'.mw-unit-btn'
				);


			const basePrice =
				parseFloat(
					box.dataset.basePrice || 0
				);


			const min =
				parseInt(
					box.dataset.min || 100,
					10
				);


			const step =
				parseInt(
					box.dataset.step || 100,
					10
				);


			let currentUnit = 'gram';

			let currentWeight = min;


			/* =====================================
			 * فرمت عدد
			 * ===================================== */

			function formatNumber( number ) {

				return new Intl.NumberFormat(
					'fa-IR'
				).format(
					Math.round( number )
				);

			}


			/* =====================================
			 * متن وزن
			 * ===================================== */

			function formatWeight( weight ) {

				weight =
					Math.round(
						weight
					);


				if ( weight < 1000 ) {

					return (
						formatNumber( weight ) +
						' گرم'
					);

				}


				const kg =
					Math.floor(
						weight / 1000
					);


				const gram =
					weight % 1000;


				if ( gram === 0 ) {

					return (
						formatNumber( kg ) +
						' کیلوگرم'
					);

				}


				return (
					formatNumber( kg ) +
					' کیلو و ' +
					formatNumber( gram ) +
					' گرم'
				);

			}


			/* =====================================
			 * نمایش Input
			 * ===================================== */

			function updateInputDisplay() {

				if (
					currentUnit === 'gram'
				) {

					input.type = 'number';

					input.value =
						currentWeight;

					input.min =
						min;

					input.step =
						step;

					inputUnit.textContent =
						'گرم';

					return;
				}


				input.type = 'text';

				input.removeAttribute(
					'min'
				);

				input.removeAttribute(
					'step'
				);


				if (
					currentWeight < 1000
				) {

					currentWeight = 1000;

				}


				const kg =
					Math.floor(
						currentWeight / 1000
					);


				const gram =
					currentWeight % 1000;


				if ( gram === 0 ) {

					input.value =
						kg;

					inputUnit.textContent =
						'کیلوگرم';

				} else {

					input.value =
						formatWeight(
							currentWeight
						);

					inputUnit.textContent =
						'';

				}

			}


			/* =====================================
			 * محاسبه قیمت
			 *
			 * basePrice = قیمت یک کیلو
			 * weight    = وزن به گرم
			 * ===================================== */

			function calculatePrice( weight ) {

				/*let price =
					(
						basePrice / 1000
					) * weight;


				price =
					Math.round(
						price / 1000
					) * 1000;


				return price;*/
				
				
				let price =
		(
			basePrice / 1000
		) * weight;

	return price;

			}


			/* =====================================
			 * بروزرسانی
			 * ===================================== */

			function updateDisplay() {

				if (
  typeof currentWeight === 'undefined' ||
  isNaN(currentWeight) ||
  currentWeight < min
) {
  currentWeight = min;
}


				const difference =
					currentWeight - min;


				if (
					difference % step !== 0
				) {

					currentWeight =
						min +
						Math.round(
							difference / step
						) * step;

				}


				if (
					currentWeight < min
				) {

					currentWeight = min;

				}


				if (
					currentUnit === 'kg' &&
					currentWeight < 1000
				) {

					currentWeight = 1000;

				}


				/*
				 * وزن واقعی
				 */

				hiddenInput.value =
					currentWeight;


				/*
				 * نمایش وزن
				 */

				updateInputDisplay();


				readableBox.textContent =
					formatWeight(
						currentWeight
					);


				/*
				 * قیمت
				 */

				const price =
					calculatePrice(
						currentWeight
					);


				priceBox.textContent =
					'قیمت: ' +
					formatNumber(
						price
					) +
					' تومان';

			}
window.addEventListener('load', updateDisplay);
updateDisplay();

			/* =====================================
			 * +
			 * ===================================== */


			plus.addEventListener('click', function () {
			  if (input.value === '') {
				currentWeight = min;
				updateDisplay();
				return;
			  }

			  currentWeight += step;
			  updateDisplay();
			});
			

			/* =====================================
			 * -
			 * ===================================== */

			minus.addEventListener(
				'click',
				function () {

					currentWeight -= step;


					if (
						currentWeight < min
					) {

						currentWeight = min;

					}


					if (
						currentUnit === 'kg' &&
						currentWeight < 1000
					) {

						currentWeight = 1000;

					}


					updateDisplay();

				}
			);


			/* =====================================
			 * ورود دستی
			 * ===================================== */

// مدیریت تایپ دستی و پاک کردن کامل فیلد
input.addEventListener('input', function () {
	if (!this.value.trim()) {
    currentWeight = (currentUnit === 'kg') ? 1000 : min;
    this.value = (currentUnit === 'kg') ? 1 : min;
    updateDisplay();
    return;
  }
  if (input.value === '') {
    currentWeight = min - step; // یا مقدار 0 بسته به لاجیک دکمه مثبت
    return;
  }
  const val = parseInt(input.value, 10);
  if (!isNaN(val)) {
    currentWeight = currentUnit === 'kg' ? val * 1000 : val;
    hiddenInput.value = currentWeight;
    readableBox.textContent = formatWeight(currentWeight);
    priceBox.textContent = 'قیمت: ' + formatNumber(calculatePrice(currentWeight)) + ' تومان';
  }
});

// سوییچ بین گرم و کیلوگرم
unitButtons.forEach(function (button) {
  button.addEventListener('click', function () {
    unitButtons.forEach(b => b.classList.remove('active'));
    button.classList.add('active');
    currentUnit = button.getAttribute('data-unit') || (button.textContent.includes('کیلو') ? 'kg' : 'gram');

    if (currentUnit === 'kg' && currentWeight < 1000) {
      currentWeight = 1000;
    }
    updateDisplay();
  });
});




unitButtons.forEach(function (button) {
  button.addEventListener('click', function () {
    unitButtons.forEach(item => item.classList.remove('active'));
    button.classList.add('active');
    currentUnit = button.dataset.unit;

    if (currentUnit === 'kg' && currentWeight < 1000) {
      currentWeight = 1000;
    }
    updateDisplay();
  });
});
});

	</script>

	<?php
}


/* =========================================================
 * 13. اعتبارسنجی وزن
 * ========================================================= */

add_filter(
	'woocommerce_add_to_cart_validation',
	'mw_validate_weight',
	10,
	3
);

function mw_validate_weight(
	$passed,
	$product_id,
	$quantity
) {

	if (
		'weight' !==
		mw_get_product_sale_type(
			$product_id
		)
	) {
		return $passed;
	}


	if (
		! isset(
			$_POST['mw_selected_weight']
		)
	) {

		wc_add_notice(
			'لطفاً وزن محصول را انتخاب کنید.',
			'error'
		);

		return false;
	}


	$settings =
		mw_get_weight_settings(
			$product_id
		);


	$weight =
		absint(
			$_POST['mw_selected_weight']
		);


	$min  = $settings['min'];
	$step = $settings['step'];


	if ( $weight < $min ) {

		wc_add_notice(
			'وزن انتخاب شده کمتر از حداقل وزن مجاز است.',
			'error'
		);

		return false;
	}


	if (
		( $weight - $min ) %
		$step !== 0
	) {

		wc_add_notice(
			'وزن انتخاب شده مطابق گام تعیین شده نیست.',
			'error'
		);

		return false;
	}


	return $passed;
}


/* =========================================================
 * 15. بازیابی اطلاعات Cart از Session
 * ========================================================= */

add_filter(
	'woocommerce_get_cart_item_from_session',
	'mw_restore_weight_cart_item',
	20,
	2
);

function mw_restore_weight_cart_item(
	$cart_item,
	$values
) {

	if (
		isset(
			$values[
				'mw_selected_weight'
			]
		)
	) {

		$cart_item[
			'mw_selected_weight'
		] =
			absint(
				$values[
					'mw_selected_weight'
				]
			);
	}


	if (
		isset(
			$values[
				'mw_base_kg_price'
			]
		)
	) {

		$cart_item[
			'mw_base_kg_price'
		] =
			(float)
			$values[
				'mw_base_kg_price'
			];
	}


	if (
		isset(
			$values[
				'mw_weight_unique_key'
			]
		)
	) {

		$cart_item[
			'mw_weight_unique_key'
		] =
			$values[
				'mw_weight_unique_key'
			];
	}


	/*
	 * =============================================
	 * مهم:
	 *
	 * یک آبجکت مستقل برای این Cart Item بساز.
	 *
	 * این کار باعث می‌شود set_price()
	 * روی ردیف‌های دیگر اثر نگذارد.
	 * =============================================
	 */

	if (
		isset(
			$cart_item['data']
		) &&
		is_a(
			$cart_item['data'],
			'WC_Product'
		)
	) {

		$cart_item['data'] =
			clone $cart_item['data'];
	}


	return $cart_item;
}


/* =============
- 16. اعمال قیمت وزن داخل Cart
- ============= */

// ۱. دریافت وزن و محاسبه مستقیم قیمت واقعی
add_filter('woocommerce_add_cart_item_data', function ($cart_item_data, $product_id, $variation_id) {
    if (!empty($_REQUEST['mw_selected_weight'])) {
        $target_id = $variation_id ? $variation_id : $product_id;
        $product   = wc_get_product($target_id);
        $weight    = floatval($_REQUEST['mw_selected_weight']);
        
        // دریافت مستقیم قیمت محصول
        $raw_price = (float) $product->get_price();

        // محاسبه قیمت بر اساس گرم
       // $calculated_price = ($raw_price / 1000) * $weight;
		$calculated_price = floatval(($raw_price / 1000) * $weight);


        $cart_item_data['custom_weight'] = $weight;
        $cart_item_data['custom_price']  = $calculated_price;
        $cart_item_data['unique_key']    = md5($target_id . '_' . $weight . '_' . microtime(true));
    }
    return $cart_item_data;
}, 50, 3);

// ۲. نمایش متادیتا در سبد خرید (وزن)
add_filter('woocommerce_get_item_data', function ($item_data, $cart_item) {
    if (!empty($cart_item['custom_weight'])) {
        $item_data[] = [
            'name'  => 'وزن',
            'value' => $cart_item['custom_weight'] . ' گرم'
        ];
    }
    return $item_data;
}, 50, 2);

// ۳. ست کردن قطعی قیمت در سبد خرید

add_action('woocommerce_before_calculate_totals', function ($cart) {
    if (is_admin() && !wp_doing_ajax()) {
        return;
    }

    foreach ($cart->get_cart() as $cart_item) {
        if (isset($cart_item['custom_price'])) {
            $cart_item['data']->set_price((float) $cart_item['custom_price']);
        }
    }
}, 9999, 1);



// ۴. اصلاح نمایش قیمت واحد در ستون قیمت سبد خرید (حل مشکل نمایش قیمت کلی)
add_filter('woocommerce_cart_item_price', function ($price_html, $cart_item, $cart_item_key) {
    if (isset($cart_item['custom_price'])) {
        return wc_price($cart_item['custom_price']);
    }
    return $price_html;
}, 9999, 3);


// ۵. اجبار خروجی HTML قیمت آیتم برای تمپلیت‌ها و مینی‌کارت‌های سفارشی
add_filter('woocommerce_cart_item_subtotal', function ($subtotal, $cart_item, $cart_item_key) {
    if (isset($cart_item['custom_price'])) {
        return wc_price($cart_item['custom_price'] * $cart_item['quantity']);
    }
    return $subtotal;
}, 99999, 3);

// ۶. اورراید کردن خروجی قیمت در سطح آبجکت محصول داخل سبد
add_filter('woocommerce_product_get_price', function ($price, $product) {
    if (is_admin() && !wp_doing_ajax()) return $price;
    
    if (WC()->cart) {
        foreach (WC()->cart->get_cart() as $cart_item) {
            if (isset($cart_item['custom_price']) && $cart_item['data'] === $product) {
                return $cart_item['custom_price'];
            }
        }
    }
    return $price;
}, 99999, 2);








/* =========================================================
 * 17. نمایش وزن در Cart
 * ========================================================= */

add_filter(
	'woocommerce_get_item_data',
	'mw_display_weight_cart',
	10,
	2
);

function mw_display_weight_cart(
	$item_data,
	$cart_item
) {

	if (
		isset(
			$cart_item[
				'mw_selected_weight'
			]
		)
	) {

		$weight =
			absint(
				$cart_item[
					'mw_selected_weight'
				]
			);


		$item_data[] = array(
			'key' => 'وزن',
			'value' =>
				mw_format_weight_text(
					$weight
				),
		);

	}


	return $item_data;
}


/* =========================================================
 * 18. ذخیره وزن داخل سفارش
 * ========================================================= */

add_action(
	'woocommerce_checkout_create_order_line_item',
	'mw_save_weight_order_item',
	10,
	4
);

function mw_save_weight_order_item(
	$item,
	$cart_item_key,
	$values,
	$order
) {

	if (
		isset(
			$values[
				'mw_selected_weight'
			]
		)
	) {

		$weight =
			absint(
				$values[
					'mw_selected_weight'
				]
			);


		$item->add_meta_data(
			'وزن',
			mw_format_weight_text(
				$weight
			),
			true
		);
	}
}

26,636 chars · codepastes.com