Category Bar - Improved Code
إكسسوارات > أغطية الحماية"
* سيتم إضافته تلقائياً إلى:
* ✅ أغطية الحماية (موجود)
* ✅ إكسسوارات (يضاف تلقائياً)
* ✅ الهواتف (يضاف تلقائياً)
*/
if (!defined('ABSPATH')) exit;
// ============================================================
// 1. هوك تلقائي: يعمل عند حفظ أي منتج
// ============================================================
add_action('woocommerce_process_product_meta', 'xcite_assign_parent_categories', 20, 1);
add_action('save_post_product', 'xcite_assign_parent_categories', 20, 1);
/**
* عند حفظ منتج: أضف جميع التصنيفات الأعلى منه
*/
function xcite_assign_parent_categories($product_id) {
// تجنب التكرار أثناء الحفظ التلقائي
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (wp_is_post_revision($product_id)) return;
// جلب تصنيفات المنتج الحالية
$current_terms = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));
if (empty($current_terms) || is_wp_error($current_terms)) return;
// جمع جميع الآباء
$all_ids = xcite_get_all_parent_ids($current_terms);
// دمج القديم مع الجديد بدون تكرار
$final_ids = array_unique(array_merge($current_terms, $all_ids));
// تحديث تصنيفات المنتج
wp_set_post_terms($product_id, $final_ids, 'product_cat');
}
/**
* جلب جميع معرفات الآباء لمجموعة من التصنيفات
*
* @param array $term_ids معرفات التصنيفات
* @return array جميع معرفات الآباء
*/
function xcite_get_all_parent_ids($term_ids) {
$parent_ids = array();
foreach ($term_ids as $term_id) {
$ancestors = get_ancestors($term_id, 'product_cat', 'taxonomy');
$parent_ids = array_merge($parent_ids, $ancestors);
}
return array_unique($parent_ids);
}
// ============================================================
// 2. دالة لمعالجة جميع المنتجات الموجودة (تشغيل مرة واحدة)
// ============================================================
/**
* معالجة جميع المنتجات الموجودة وإضافة الآباء الناقصين
* شغّلها مرة واحدة فقط من WP-CLI أو admin
*/
function xcite_fix_all_products_parent_categories($batch_size = 100) {
$page = 1;
$fixed = 0;
$skipped = 0;
echo "بدء معالجة جميع المنتجات...\n";
do {
$products = wc_get_products(array(
'status' => array('publish', 'draft', 'private'),
'limit' => $batch_size,
'page' => $page,
'return' => 'ids',
));
if (empty($products)) break;
foreach ($products as $product_id) {
$current_terms = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));
if (empty($current_terms) || is_wp_error($current_terms)) {
$skipped++;
continue;
}
// جلب جميع الآباء
$parent_ids = xcite_get_all_parent_ids($current_terms);
// التحقق إذا كانت هناك آباء ناقصة
$missing = array_diff($parent_ids, $current_terms);
if (!empty($missing)) {
$final_ids = array_unique(array_merge($current_terms, $parent_ids));
wp_set_post_terms($product_id, $final_ids, 'product_cat');
$fixed++;
} else {
$skipped++;
}
}
echo "صفحة {$page}: تمت معالجة " . count($products) . " منتج (مُصلح: {$fixed}, تخطي: {$skipped})\n";
$page++;
} while (count($products) === $batch_size);
echo "\n✅ اكتمل!\n";
echo "تم تصحيح: {$fixed} منتج\n";
echo "لم يحتج تصحيح: {$skipped} منتج\n";
}
// ============================================================
// 3. زر في لوحة التحكم لتشغيل المعالجة الجماعية
// ============================================================
add_action('admin_menu', function () {
add_submenu_page(
'woocommerce',
'إصلاح التصنيفات الأب',
'إصلاح التصنيفات الأب',
'manage_woocommerce',
'xcite-fix-categories',
'xcite_fix_categories_page'
);
});
function xcite_fix_categories_page() {
$message = '';
if (isset($_POST['xcite_fix_cats']) && check_admin_referer('xcite_fix_cats_nonce')) {
ob_start();
xcite_fix_all_products_parent_categories();
$output = ob_get_clean();
$message = $output;
update_option('xcite_parent_cats_fixed', current_time('mysql'));
}
$last_run = get_option('xcite_parent_cats_fixed', 'لم يتم التشغيل بعد');
?>
🗂️ إصلاح التصنيفات الأب
هذه الأداة تمر على جميع المنتجات وتضيف لها جميع التصنيفات الأعلى منها تلقائياً.
مثال: منتج في الهواتف > إكسسوارات > أغطية الحماية سيُضاف أيضاً إلى إكسسوارات و الهواتف
آخر تشغيل:
const lazyloadRunObserver = () => {
const lazyloadBackgrounds = document.querySelectorAll( `.e-con.e-parent:not(.e-lazyloaded)` );
const lazyloadBackgroundObserver = new IntersectionObserver( ( entries ) => {
entries.forEach( ( entry ) => {
if ( entry.isIntersecting ) {
let lazyloadBackground = entry.target;
if( lazyloadBackground ) {
lazyloadBackground.classList.add( 'e-lazyloaded' );
}
lazyloadBackgroundObserver.unobserve( entry.target );
}
});
}, { rootMargin: '200px 0px 200px 0px' } );
lazyloadBackgrounds.forEach( ( lazyloadBackground ) => {
lazyloadBackgroundObserver.observe( lazyloadBackground );
} );
};
const events = [
'DOMContentLoaded',
'elementor/lazyload/observe',
];
events.forEach( ( event ) => {
document.addEventListener( event, lazyloadRunObserver );
} );