أهلاً بيك في المقال رقم 37 من 100 في سلسلتنا المعمارية الشاملة معمارية ووردبريس من الأساسيات إلى الاحتراف الكامل، ضمن المستوى الرابع: معمارية الإضافات (Plugin Architecture). النهاردة هنتكلم عن الوجه الآخر لدورة حياة الإضافة، واللحظة التي تفرق بين المطور المحترف والهاوي الذي قد يدمر بيانات عملائه في غمضة عين: خطاف تعطيل الإضافات (register_deactivation_hook)، وإدارة تنظيف المهام المجدولة، وحفظ البيانات الدائمة، وتحديث الروابط بالعامية المصرية.
تخيل معايا الكارثة دي اللي حصلت في إحدى كبرى شركات العقارات في الجيزة: الشركة عندها إضافة مخصصة لإدارة بيانات العملاء والليدز (Leads) فيها أكثر من 35,000 عميل مسجل. مسؤول التسويق في الشركة حب يجرب إضافة جديدة، فدخل على لوحة التحكم وضغط على زرار “تعطيل” (Deactivate) لإضافة الـ CRM لمدة ربع ساعة عشان يشوف تعارض بسيط في التصميم. بعد ما خلص تجاربه، رجع فعل الإضافة تاني.. وكانت المفاجأة المرعبة: كل بيانات الـ 35 ألف عميل اتمسحت تماماً وقاعدة البيانات رجعت بيضاء كأنها لسه متسطبة! ليه الكارثة دي حصلت؟ لأن المبرمج اللي كتب الإضافة كان حاطط كود DROP TABLE ومسح الخيارات جوه خطاف التعطيل register_deactivation_hook! في المقال ده، هنشرح الفارق الفلسفي والمعماري الصارم بين “التعطيل” و”الحذف النهائي”، وإيه اللي المفروض تنظفه وإيه اللي خط أحمر ممنوع تلمسه أثناء التعطيل.
الفلسفة المعمارية: التعطيل المؤقت مقابل الحذف النهائي
في معمارية ووردبريس، هناك قاعدة مقدسة يجب أن يحفظها كل مهندس برمجيات:
التعطيل (Deactivation) إجراء مؤقت وقابل للعكس.. أما الحذف (Uninstall) فهو قرار نهائي برحيل الإضافة!
المستخدم أو مدير الموقع قد يقوم بتعطيل إضافتك لعدة أسباب مؤقتة مشروعة:
- تشخيص تعارض محتمل مع إضافة أخرى أو فحص بطء في القالب (Troubleshooting).
- ترقية الإضافة يدوياً برفع ملف zip جديد.
- إيقاف مؤقت لميزة معينة لفترة قصيرة وإعادة تفعيلها لاحقاً.
إذا قمت بحذف بيانات المستخدم أو مسح جداوله في لحظة التعطيل، فأنت ترتكب جريمة برمجية كاملة! العميل يتوقع أنه عندما يعيد تفعيل الإضافة بعد 10 دقائق أو أسبوع، أن يجد كافة إعداداته، ومنشوراته، وحساباته، وجداوله كما تركها تماماً دون أن ينقص منها حرف واحد.
ما هو المسموح بتنظيفه وما هو المحظور لمسه أثناء التعطيل؟
عشان نحدد المسؤوليات المعمارية بدقة، الجدول التالي يوضح خريطة العمليات المسموحة والممنوعة في خطاف التعطيل:
| الكيان البرمجي في النظام | السلوك المعماري في خطاف التعطيل (Deactivation) | السلوك المعماري في ملف الحذف (Uninstall) |
|---|---|---|
| جداول MySQL المخصصة | محظور لمسها تماماً (تبقى سليمة 100%) | تحذف نهائياً بـ DROP TABLE إذا رغب العميل |
| خيارات الإعدادات (Options API) | محظور مسحها (تبقى محفوظة) | تحذف بـ delete_option() لتنظيف الجدول |
| بيانات المنشورات والميتا (CPTs & Meta) | محظور مسحها نهائياً | تحذف كافة سجلات المنشورات والميتا التابعة |
| مهام الكرون المجدولة (WP-Cron) | تنظف وتحذف فوراً بـ wp_clear_scheduled_hook | تحذف كافة المهام المجدولة المتبقية |
| قواعد التوجيه (Rewrite Rules) | تحدث وتفرغ بـ flush_rewrite_rules | تفرغ قواعد التوجيه لإزالة المسارات الميتة |
| الكاش المؤقت (Transients API) | تحذف بـ delete_transient لتنظيف الذاكرة | تحذف كافة مفاتيح الكاش التابعة للإضافة |
التشريح الداخلي لخطاف register_deactivation_hook
عندما يضغط المدير على رابط “تعطيل” في لوحة التحكم، يرسل المتصفح طلباً يحمل توكن أمان (Nonce). في هذه اللحظة ينفذ ووردبريس الخطوات التالية:
- يستدعي دالة
deactivate_plugins(). - يطلق خطاف النواة الداخلي
deactivate_{$plugin}الذي يستدعي الـ Callback المسجل عبر دالةregister_deactivation_hook( __FILE__, 'callback' ). - يقوم ووردبريس بحذف مسار الإضافة من مصفوفة
active_pluginsفي جدولwp_options. - يفرغ كاش الكائنات لمصفوفة الإضافات، ويعيد توجيه المتصفح إلى
plugins.php?deactivate=trueمع إشعار “تم تعطيل الإضافة بنجاح”.
المهام المعمارية الأساسية الواجب تنفيذها أثناء التعطيل
هناك مهمتان أساسيتان لا يجوز لأي إضافة محترفة إغفالهما عند التعطيل:
1. تنظيف وإلغاء مهام الكرون المجدولة (WP-Cron Cleanup)
إذا كانت إضافتك قد قامت أثناء التفعيل بجدولة مهمة دورية (مثلاً فحص أسعار العملات يومياً عبر wp_schedule_event)، وقام المستخدم بتعطيل الإضافة دون تنظيف الحدث، فماذا سيحدث؟
سيبقى الحدث مسجلاً في جدول wp_options تحت خيار cron! وعندما يحل ميعاد التنفيذ، سيحاول نظام WP-Cron استدعاء دالة الـ Callback الخاصة بإضافتك، ولكن لأن الإضافة معطلة، الدالة غير موجودة في الذاكرة! هذا يؤدي إلى تسجيل تحذيرات مستمرة في ملف debug.log واستهلاك دورات معالجة غير ضرورية على السيرفر.
لذلك، يجب دائماً استدعاء دالة wp_clear_scheduled_hook('my_cron_hook') أثناء التعطيل.
2. تجديد قواعد التوجيه وإزالة مسارات الـ CPTs
عندما تتعطل الإضافة، فإن أنواع المحتوى والتصنيفات التابعة لها لم تعد مسجلة في النواة. إذا لم يتم تحديث الروابط الدائمة، ستظل قواعد التوجيه القديمة (Rewrite Rules) مخزنة في قاعدة البيانات وتحاول توجيه الزوار لمسارات ملغاة. استدعاء flush_rewrite_rules(false) أثناء التعطيل يضمن إزالة هذه القواعد فوراً، وبقاء مسارات الموقع نظيفة وسريعة.
معمارية التعطيل الشبكي في Multisite
في شبكات المواقع المتعددة (WordPress Multisite)، دالة الـ Callback المربوطة بـ register_deactivation_hook تستقبل أيضاً معاملاً منطقياً $network_wide يوضح ما إذا كان التعطيل قد تم من لوحة إدارة الشبكة (Network Admin):
- إذا كان
$network_wide = true: يجب على السكريبت الدوران عبر كافة المواقع الفرعية باستخدامswitch_to_blog()لإلغاء مهام الكرون المجدولة وتحديث الروابط في كل موقع فرعي على حدة. - إذا كان
$network_wide = false: يتم التنظيف للموقع الحالي فقط.
الكود البرمجي الكامل: كلاس التعطيل المؤسسي الآمن (Safe Enterprise Deactivator)
الكود التالي يمثل النموذج المعماري القياسي لإدارة دورة حياة التعطيل؛ حيث يقوم بتنظيف مهام الكرون، وتحديث مسارات التوجيه، وإلغاء الكاش المؤقت، ودعم شبكات Multisite مع الحفاظ التام والكامل على بيانات العميل وجداول MySQL:
<?php
/**
* كلاس معالجة دورة حياة تعطيل الإضافة بأمان تام
*/
final class Abozaid_Plugin_Deactivator {
/**
* نقطة الدخول الرئيسية لخطاف التعطيل
*
* @param bool $network_wide هل تم التعطيل على مستوى الشبكة بالكامل؟
*/
public static function deactivate( bool $network_wide = false ): void {
if ( is_multisite() && $network_wide ) {
// الدوران على كافة المواقع الفرعية في الشبكة لتنظيف المهام والروابط
$site_ids = get_sites( [ 'fields' => 'ids', 'number' => 0 ] );
foreach ( $site_ids as $site_id ) {
switch_to_blog( (int) $site_id );
self::run_single_site_deactivation();
restore_current_blog();
}
} else {
self::run_single_site_deactivation();
}
}
/**
* تنفيذ مهام التنظيف المؤقت للموقع الواحد
*/
private static function run_single_site_deactivation(): void {
// 1. إلغاء وحذف كافة مهام الكرون المجدولة التابعة للإضافة
wp_clear_scheduled_hook( 'abozaid_daily_cleanup_cron' );
wp_clear_scheduled_hook( 'abozaid_warm_market_transient_event' );
// 2. تحديث وتفريغ قواعد التوجيه لإزالة مسارات الـ CPTs المعطلة
flush_rewrite_rules( false );
// 3. حذف الكاش المؤقت والبيانات السريعة الزوال
delete_transient( 'az_market_gold_prices' );
delete_transient( 'az_egp_exchange_rates' );
// 4. تطهير كاش الكائنات في الذاكرة ومزامنة Redis
wp_cache_flush();
// تنبيه معماري حاسم:
// نحن لا نقوم بحذف جداول قاعدة البيانات هنا!
// نحن لا نمس خيارات الإعدادات في wp_options هنا!
// نحن لا نحذف منشورات العملاء هنا!
// كافة البيانات الدائمة تبقى محفوظة للأبد حتى يطلب العميل الحذف النهائي.
}
}
// تسجيل الخطاف في الملف الرئيسي للإضافة
register_deactivation_hook( AZ_CORE_FILE, [ 'Abozaid_Plugin_Deactivator', 'deactivate' ] );
?>دراسة حالة واقعية من السوق المصري: فقدان 35 ألف عميل بسبب خطأ في كود التعطيل
في إحدى كبرى شركات التطوير العقاري في مصر، الشركة كانت تدير قاعدة بيانات استثمارية تضم أكثر من 35,000 عميل مهتم بشراء فلل وشقق في الساحل الشمالي والعاصمة الإدارية. كانت الشركة تستخدم إضافة CRM مخصصة برمجها فريق سابق. في أحد الأيام، لاحظ مسؤول الحملات الإعلانية تعارضاً في شكل أزرار الموقع مع إضافة تسويق جديدة، فقام بالضغط على زر “تعطيل” لإضافة الـ CRM لاختبار الصفحة.
الكارثة وجذور الخطأ البرمجي
عند فحص كود الملف الرئيسي للإضافة المعطلة، وجدنا الكود الكارثي التالي:
// كود كارثي دمر بيانات العميل بالكامل
register_deactivation_hook( __FILE__, function() {
global $wpdb;
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}az_crm_leads" );
delete_option( 'az_crm_settings' );
} );المبرمج السابق كان يجهل تماماً الفرق بين التعطيل والحذف النهائي! وافترض بسذاجة أن المستخدم إذا عطل الإضافة فهو لا يريد بياناتها! بمجرد ضغط زر التعطيل، أرسل السيرفر أمر DROP TABLE فورياً لمحرك MySQL، وتم مسح جدول العملاء بالكامل في أقل من ثانية واحدة، وضاعت أرقام هواتف وتفاصيل حجوزات تقدر بملايين الجنيهات!
خطة الإنقاذ الهندسي والتحصين المعماري
- تم استدعاء خبير استعادة قواعد البيانات، ونجحنا في استخراج نسخة احتياطية (Binlog Recovery) من خادم السيرفر السحابي تم أخذها قبل الحادث بـ 4 ساعات، واستعدنا 99.8% من بيانات العملاء.
- تم مسح كود
DROP TABLEوdelete_optionتماماً من خطاف التعطيل. - تم نقل منطق الحذف النهائي والتطهير بالكامل إلى ملف
uninstall.phpالمستقل، مع إضافة خيار أمني في لوحة تحكم الإضافة يقول: “هل تريد حذف كافة البيانات عند إلغاء التثبيت؟ (الافتراضي: لا)”، بحيث لا يتم حذف أي سجل إلا إذا طلب المدير ذلك صراحة وبوعي كامل قبل الحذف.
النتيجة: تم تأمين أصول الشركة الرقمية بنسبة 100%، وتم وضع معيار صارم يجرم حذف أي بيانات في خطاف التعطيل.
الوصايا العشر لإدارة خطاف تعطيل الإضافات
- لا تحذف جداول MySQL في خطاف التعطيل نهائياً: التعطيل إجراء مؤقت، وحذف الجداول خيانة لثقة العميل وأمان بياناته.
- نظف مهام الكرون بـ wp_clear_scheduled_hook: امنع تراكم المهام الشبحية المعلقة في خيار
cronبقاعدة البيانات. - فرغ قواعد التوجيه بـ flush_rewrite_rules: تأكد من إزالة مسارات CPTs المعطلة لتفادي أخطاء الروابط المكسورة.
- احذف الكاش المؤقت والـ Transients: طهر الذاكرة وجدول الخيارات من البيانات المؤقتة التي لم يعد لها داعٍ.
- ادعم شبكات Multisite بحذر: تأكد من تنظيف مهام الكرون في كافة المواقع الفرعية عند التعطيل الشبكي الكامل.
- لا تطبع أي نصوص أو مسافات (No Output): خطاف التعطيل حساس تماماً لمجاري الإخراج ومحمي بنظام الـ Buffering.
- احتفظ بإعدادات المستخدم في Options: دع العميل يجد إعداداته جاهزة ومحفوظة إذا قرر إعادة تفعيل الإضافة لاحقاً.
- احفظ منطق الحذف لملف uninstall.php: هذا هو المكان الشرعي والوحيد المعتمد من ووردبريس لمسح الجداول والإعدادات.
- لا تعطل إضافات أخرى داخل خطاف التعطيل: التزم بمسؤوليات إضافتك فقط ولا تتدخل في دورة حياة الإضافات الشقيقة.
- اختبر التعطيل وإعادة التفعيل مراراً: تأكد من أن الموقع يعمل بسلاسة بعد التعطيل، وأن إعادة التفعيل تعيد كل شيء للعمل بكفاءة تامة.
الأسئلة الشائعة حول خطاف تعطيل الإضافات في ووردبريس
إلغاء اشتراكات الخدمات السحابية والـ Webhooks الخارجية بأمان عند التعطيل
في كثير من الإضافات الحديثة، لا يعيش النظام بمعزل عن العالم الخارجي؛ فالإضافة تكون مربوطة بخدمات سحابية خارجية (مثل بوابات الدفع الإلكتروني، منصات الرسائل القصيرة Twilio، خدمات الإشعارات الفورية Firebase، أو أنظمة الـ CRM الخارجية مثل HubSpot وSalesforce). هذه الخدمات تعتمد على Webhooks مرسلة من السيرفر الخارجي إلى موقع ووردبريس فور وقوع أحداث معينة.
ما هي الكارثة الصامتة التي تحدث إذا قمت بتعطيل الإضافة دون إلغاء هذه الاشتراكات؟
الخدمة السحابية الخارجية (مثل بوابة الدفع أو مزود الرسائل) لا تعلم أنك قمت بتعطيل الإضافة! فتظل ترسل آلاف طلبات الـ HTTP إلى رابط الـ Webhook الخاص بك (مثلاً /wp-json/az-gateway/v1/webhook). وحيث إن الإضافة معطلة، يعيد ووردبريس خطأ 404 Not Found أو 500 Internal Error. عندما تتكرر الأخطاء، تقوم أنظمة الحماية لدى مزود الخدمة الخارجي بـ تعطيل حساب التاجر مؤقتاً أو حظر الـ IP الخاص بموقعك (IP Blacklisting) بسبب تكرار الفشل!
الكود البرمجي لمصافحة إلغاء الاشتراك الخارجي (Webhook Deregistration Handshake)
الحل المعماري الذكي هو إرسال طلب HTTP DELETE فوري ومحكم لمزود الخدمة الخارجي لإلغاء تسجيل رابط الـ Webhook مؤقتاً أثناء تنفيذ خطاف التعطيل، مع وضع مهلة زمنية صارمة (Strict Timeout لا تتجاوز ثانيتين) لضمان عدم تعليق لوحة تحكم ووردبريس إذا كان السيرفر الخارجي بطيئاً:
<?php
/**
* إلغاء تسجيل الـ Webhooks الخارجية بأمان عند تعطيل الإضافة
*/
function abozaid_deregister_external_webhooks(): void {
$settings = get_option( 'abozaid_payment_settings', [] );
$api_key = $settings['api_key'] ?? '';
$webhook_id = get_option( 'az_remote_webhook_id', '' );
if ( empty( $api_key ) || empty( $webhook_id ) ) {
return;
}
// إرسال طلب إلغاء الاشتراك بمزود الخدمة بمهلة اتصال سريعة جداً
$response = wp_remote_request( "https://api.external-gateway.com/v1/webhooks/{$webhook_id}", [
'method' => 'DELETE',
'timeout' => 2, // ثانيتان فقط لضمان سرعة إكمال التعطيل
'headers' => [
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/json',
],
'sslverify' => true,
] );
if ( ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response ) ) {
// حذف معرف الـ Webhook من الخيارات المحلية لضمان إعادة تسجيله عند التفعيل القادم
delete_option( 'az_remote_webhook_id' );
}
}
?>تطهير كاش الحافة (Cloudflare / Fastly CDN Purge) أثناء التعطيل
في المواقع الكبيرة التي تعتمد على شبكات توزيع المحتوى (CDNs) لتخزين الصفحات الثابتة وكاش الـ HTML، تعطيل إضافة تقدم ميزات في الواجهة الأمامية (مثل شريط إعلاني علوي أو زر محادثة واتساب عائم) يتطلب إشعاراً فورياً لشبكة الـ CDN لتطهير النسخ المخبأة.
لو لم تقم بتطهير الكاش أثناء التعطيل، سيظل زوار موقعك يشاهدون كود الإضافة المعطلة وملفات الجافاسكريبت المفقودة لساعات طويلة من كاش الـ CDN، مما يسبب أخطاء جافاسكريبت وتشوهات بصرية! استدعاء خطاف التعطيل لتفريغ وسوم الكاش (Cache-Tags) التابعة للإضافة يضمن اختفاء كافة أثارها من شاشات المستخدمين في نفس اللحظة.
تسجيل عمليات التعطيل في سجلات النشاط (Audit Telemetry)
في بيئات العمل المؤسسية التي يعمل عليها فرق متعددة (مديرو تسويق، مطورون، مسؤولو أمان)، من الضروري جداً معرفة من قام بتعطيل الإضافة ومتى ولماذا؟
النواة تتيح لك عبر خطاف deactivated_plugin تسجيل عملية التعطيل في ملف سجلات الأمان أو إرسال إشعار لقناة سلاك الداخلية:
<?php
/**
* تسجيل وتوثيق عملية تعطيل الإضافات لمسؤولي الأمان
*
* @param string $plugin مسار الإضافة المعطلة
* @param bool $network_wide هل التعطيل شبكي
*/
add_action( 'deactivated_plugin', 'abozaid_log_plugin_deactivation_event', 10, 2 );
function abozaid_log_plugin_deactivation_event( string $plugin, bool $network_wide ): void {
$current_user = wp_get_current_user();
$user_name = $current_user->exists() ? $current_user->user_login : 'CLI/System';
$ip_address = sanitize_text_field( $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1' );
$log_entry = sprintf(
'[%s] تنبيه أمني: قام المستخدم "%s" (IP: %s) بتعطيل الإضافة "%s" (شبكياً: %s).',
current_time( 'mysql' ),
$user_name,
$ip_address,
$plugin,
$network_wide ? 'نعم' : 'لا'
);
error_log( '[Abozaid Security Audit] ' . $log_entry );
}
?>هذا التوثيق المعماري يحمي فريق التطوير من الاتهامات العشوائية، ويوضح بدقة متناهية تسلسل الأحداث التشغيلية على الخادم.
س1: ما هو الفرق الجوهري بين خطاف التعطيل (Deactivation) وملف الحذف (Uninstall)؟
خطاف التعطيل ينفذ عند إيقاف الإضافة مؤقتاً ولا يجوز فيه حذف أي بيانات دائمة أو جداول، بل يقتصر على تنظيف مهام الكرون وتحديث الروابط. بينما ملف Uninstall ينفذ فقط عند قيام المستخدم بالضغط الصريح على زر “حذف” بعد التعطيل، وهو المخصص لمسح الجداول والإعدادات نهائياً.
س2: لماذا يعد حذف جداول قاعدة البيانات في خطاف التعطيل خطأً فادحاً؟
لأن المستخدم قد يعطل الإضافة مؤقتاً لتشخيص تعارض برمجي أو لترقيتها، وحذف الجداول في هذه اللحظة يؤدي لفقدان كافة بيانات العملاء والطلبات والتاريخ التشغيلي للموقع دون إذن منه.
س3: ما هي أهم المهام التي يجب تنفيذها أثناء تعطيل الإضافة؟
إلغاء مهام الكرون المجدولة عبر wp_clear_scheduled_hook()، وتحديث قواعد التوجيه عبر flush_rewrite_rules()، وحذف الكاش المؤقت المرتبط عبر delete_transient().
س4: ماذا يحدث إذا لم نقم بإلغاء مهام الكرون أثناء التعطيل؟
تبقى المهام مسجلة في جدول wp_options تحت خيار cron، ويحاول ووردبريس استدعاء دوالها في كل دورة دون جدوى، مما يملأ سجلات الأخطاء بتحذيرات مستمرة ويستهلك موارد الخادم.
س5: كيف يتعامل خطاف التعطيل مع شبكات المواقع المتعددة (Multisite Network Deactivate)؟
يستقبل خطاف التعطيل معاملاً يوضح ما إذا كان التعطيل شبكياً $network_wide، ويجب على المطور الدوران عبر كافة المواقع الفرعية بـ switch_to_blog() لإلغاء مهام الكرون وتحديث الروابط في كل موقع.
س6: هل يمكن طباعة رسالة وداع أو استبيان للعميل أثناء التعطيل مباشرة في خطاف التعطيل؟
لا يجوز ذلك داخل خطاف register_deactivation_hook لأنه محمي بنظام Output Buffering وأي طباعة ستسبب أخطاء، ولكن يمكن استخدام كود جافاسكريبت في صفحة plugins.php لعرض نافذة منبثقة عند الضغط على زر التعطيل.
س7: أين يجب استدعاء دالة register_deactivation_hook في ملفات الإضافة؟
يجب استدعاؤها في الملف الرئيسي للإضافة في النطاق العام، وتمرير الثابت __FILE__ كمعامل أول واسم دالة الـ Callback كمعامل ثانٍ.
س8: هل تعمل دالة register_deactivation_hook داخل إضافات Must-Use (MU-Plugins)؟
لا تعمل نهائياً؛ لأن إضافات MU تعمل إلزامياً ومستمرة دائماً ولا تمر بمسار التعطيل في لوحة التحكم، ولذلك لا يتم إطلاق هذا الخطاف لها إطلاقاً.
س9: هل يجب حذف الأدوار المخصصة (Custom Roles) أثناء التعطيل؟
الأفضل عدم حذفها في التعطيل العادي إذا كان هناك مستخدمون مسندون إليها حتى لا تصبح حساباتهم معلقة بدون دور، ولكن يمكن حذفها في ملف uninstall.php عند الحذف النهائي بعد إعادة إسناد المستخدمين.
س10: ماذا يحدث لقواعد التوجيه (Rewrite Rules) إذا لم نقم بتفريغها عند التعطيل؟
تبقى مسارات الـ CPTs والـ Taxonomies الخاصة بالإضافة معلقة في قاعدة البيانات، وإذا حاول الزوار فتح روابط مشابهة قد تتداخل مع مسارات الصفحات الأخرى وتسبب أخطاء غير متوقعة.
س11: كيف أتحقق من أن دالة التعطيل تعمل بنجاح دون أي أخطاء؟
عبر تفعيل WP_DEBUG ومراجعة ملف debug.log فور ضغط زر التعطيل في لوحة التحكم، والتأكد من عدم تسجيل أي تحذيرات أو أخطاء استدعاء.
س12: هل يمكن تعطيل إضافة برمجياً من داخل كود إضافة أخرى؟
نعم، باستخدام دالة النواة الرسمية deactivate_plugins('plugin-folder/plugin-file.php')، مع التحقق من امتلاك المستخدم الحالي للصلاحيات الإدارية الكافية.
س13: ما هو الخطاف الذي ينطلق بعد اكتمال تعطيل الإضافة وإعادة التوجيه؟
الخطاف المعماري العام هو deactivated_plugin ويمرر مسار الإضافة المعطلة، ويستخدم غالباً لتسجيل عمليات التعطيل في سجلات النشاط (Audit Logs).
س14: كيف أحذف Transients متعددة تابعة لإضافتي دفعة واحدة عند التعطيل؟
باستدعاء delete_transient() لكل مفتاح معروف، أو تنفيذ استعلام SQL سريع يحذف كافة المفاتيح التي تبدأ ببادئة إضافتك من جدول wp_options.
س15: هل يؤثر تعطيل الإضافة على الملفات المرفوعة في مجلد uploads؟
لا يؤثر نهائياً؛ كافة الصور والمستندات والملفات المرفوعة تبقى محفوظة في مكانها دون أي تعديل.
س16: ماذا يحدث إذا قام العميل بتعطيل إضافة ثم حذف مجلدها يدوياً عبر FTP؟
في هذه الحالة لن ينطلق ملف uninstall.php، وستبقى الجداول والخيارات في قاعدة البيانات، ولذلك ينصح دائماً بوضع خيار لتنظيف البيانات من داخل إعدادات الإضافة لمن يفضلون الحذف اليدوي.
س17: كيف أضمن عدم حذف بيانات العميل حتى لو قام مبرمج مبتدئ بتعديل الكود مستقبلاً؟
بفصل كود التعطيل في كلاس مستقل وتوثيق الوظائف بوضوح مع وضع تعليقات تحذيرية صارمة تمنع إضافة أي استعلامات DROP TABLE أو مسح دائم داخل خطاف التعطيل.
س18: هل يمكن إعادة توجيه المتصفح لصفحة استبيان عند التعطيل؟
تستخدم بعض الشركات فلتر plugin_action_links لربط زر التعطيل بنافذة Modal تسأل المستخدم عن سبب التعطيل قبل إرسال طلب التعطيل الفعلي للنواة.
س19: كيف يتم تنظيف كاش الذاكرة المشترك (Redis) عند تعطيل إضافة كبرى؟
باستدعاء دالة wp_cache_flush() لضمان مسح كافة المفاتيح المحملة في الذاكرة وإجبار النظام على قراءة الحالة الجديدة بدون كود الإضافة المعطلة.
س20: ما هو الفرق بين تعطيل الإضافة من لوحة التحكم وتعطيلها عبر أمر WP-CLI؟
كلاهما ينفذ نفس خطاف register_deactivation_hook ونفس مسار النواة، ولكن أمر WP-CLI wp plugin deactivate ينفذ في بيئة سطر الأوامر دون قيود مهلة المتصفح.
المصادر والمراجع الرسمية
إلغاء مهام WP-Cron وفحص الطوابير عبر WP-CLI أثناء التعطيل
لو أنت شغال في بيئة إنتاجية كبيرة بتعتمد على نظام إدارة السيرفرات وأتمتة العمليات عبر السطر البرمجي، أحياناً مدير النظام (DevOps Engineer) بيعطل الإضافة من خلال سطر الأوامر بواسطة أمر wp plugin deactivate my-enterprise-plugin. في اللحظة دي، وردبريس هينفذ هوك التعطيل المسجل طبيعي جداً. ولكن كمهندس ووردبريس محترف، لازم تضمن إن فريق العمليات يقدر يفحص ويتحقق بنفسه من إن كل طوابير الجدولة اتصفرت تماماً وما فيش أي بقايا متعلقة بتنفيذ العمليات في الخلفية.
عشان تتأكد إن المهام المجدولة اتمسحت بنجاح بعد التعطيل، بتنفذ الأمر التالي في التيرمينال:
# فحص جدول المهام المجدولة والتأكد من خلوه من مهام الإضافة المعطلة
wp cron event list --fields=hook,next_run,recurrence | grep enterprise_
# حذف أي مهمة شاردة يدوياً في حال تم التعطيل بدون تشغيل الهوك (Force Deactivation)
wp cron event delete enterprise_sync_orders_cron
wp cron event delete enterprise_cleanup_logs_cron
الخطوة دي بتعتبر من أهم المعايير القياسية في مراجعة كود إضافات الشركات الكبرى؛ لأن ترك مهام مجدولة بعد التعطيل بيتسبب في أخطاء fatal errors متكررة لو الكرون الخارجي حاول يستدعي دالة غير موجودة في الذاكرة، وده بيملا ملفات debug.log بآلاف السطور يومياً وبيستهلك مساحة التخزين وموارد الخادم على الفاضي بدون أي فائدة حقيقية.
- 🔗 WordPress Developer Reference: register_deactivation_hook() – التوثيق الرسمي لخطاف تعطيل الإضافات والمعايير الهندسية لتنفيذه.
- 🔗 WordPress Plugin Handbook: Deactivation Best Practices – أفضل الممارسات المعتمدة لإدارة مهام التعطيل والحفاظ على بيانات العملاء.
- 🔗 WordPress Developer Reference: wp_clear_scheduled_hook() – الدليل القياسي لإلغاء وتنظيف مهام الكرون المجدولة في النواة.


اترك تعليقاً
يجب أنت تكون مسجل الدخول لتضيف تعليقاً.