تخيل إنك نقلت 200 فعالية من EventON لإضافة جديدة، وتاني يوم تلاقي ورشة الساعة 6:30 مساءً بقت 9:30 بالليل. مفيش حاجة اتكسرت ظاهريًا، بس كل المواعيد اتزحزحت بنفس الفارق. السبب واحد، وهتعرفه في الدقايق الجاية قبل ما تبدأ النقل.
إضافة (Plugin) EventON من أشهر إضافات تقويم الفعاليات في ووردبريس (WordPress)، ولها نسخة مدفوعة على CodeCanyon ونسخة مجانية باسم EventON Lite. المشكلة أن حقلَي البداية والنهاية يبدوان كطابع يونكس الزمني (Unix Timestamp) عادي، لكنهما ليسا كذلك.
يعتمد هذا الشرح على تحليل كاتب المقال الأصلي لكود EventON Lite 2.5.9. النسخة المدفوعة تستخدم غالبًا نفس نوع المحتوى ونفس الحقول، لكن راجع عدة فعاليات من موقعك قبل أن تعتمد على أي شيء هنا.
أين تُخزَّن بيانات الفعاليات؟
كل فعالية هي مقالة من نوع المحتوى المخصص (Custom Post Type) ajde_events، وبقية البيانات موزعة بين بيانات المقالة الوصفية (Post Meta) والتصنيفات المخصصة (Taxonomies):
| البيان | مكان التخزين |
|---|---|
| وقت البداية والنهاية | evcal_srow وevcal_erow |
| — | — |
| المنطقة الزمنية للفعالية | _evo_tz |
| فعالية طوال اليوم | evcal_allday = "yes" |
| إعدادات التكرار | evcal_repeat وevcal_rep_freq وevcal_rep_gap وحقول أخرى |
| كل المواعيد المولَّدة | repeat_intervals |
| الأماكن والمنظمون | التصنيفان event_location وevent_organizer |
| أنواع الفعاليات | event_type ثم event_type_2 وevent_type_3… |
| لون الفعالية | evcal_event_color (قيمة hex بدون #) |
| الحالة | _status |
| رابط البث الأونلاين | _vir_url |
قيم الحقل _status هي: scheduled أو cancelled أو rescheduled أو postponed أو movedonline أو tentative أو preliminary. اكتب لكل قيمة ما يقابلها في الإضافة الجديدة قبل أن تبدأ.
الفخ الأول: التوقيت “الوهمي”
عندما تحفظ فعالية تبدأ 6:30 مساءً، يبني EventON الطابع الزمني بتوقيت UTC مباشرةً من الساعة التي كتبتها. أي أن evcal_srow يساوي 18:30 UTC مهما كانت منطقتك الزمنية. هو في الحقيقة توقيت محلي يتنكر في صورة UTC.
لو موقعك مضبوط على توقيت القاهرة، ففارق التوقيت عن UTC (UTC Offset) هو +2 شتاءً و+3 صيفًا بعد عودة التوقيت الصيفي في مصر. ولو على الرياض أو الكويت فالفارق +3 طوال العام. التحويل “الطبيعي” سيضيف هذا الفارق لكل فعالية.
هذا الكود خاطئ على أي موقع ليس على UTC، لأن wp_date() تطبّق منطقة الموقع الزمنية:
// Wrong: shifts the event by the site's offset.
$start = wp_date( 'Y-m-d H:i', (int) get_post_meta( $id, 'evcal_srow', true ) );
والصحيح أن تقرأ الرقم كما خُزِّن، أي كـ UTC، ثم تأخذ المنطقة الزمنية من حقلها المنفصل:
// The stored number is wall-clock time encoded as UTC, so read it back as UTC.
$start = gmdate( 'Y-m-d H:i', (int) get_post_meta( $id, 'evcal_srow', true ) );
$zone = get_post_meta( $id, '_evo_tz', true ) ?: wp_timezone_string();
نفس المشكلة في SQL
الدالة FROM_UNIXTIME() في السيرفر.">MySQL تحوّل الرقم حسب المنطقة الزمنية للجلسة. لذلك اضبط الجلسة على UTC أولًا وإلا ظهر نفس الانزياح في نتائج ومنشئ الاستعلامات مع القالب كاملًا والنماذج والنوافذ المنبثقة.">Elementor.">JetEngine تبني الاستعلامات بصريًا بمنشئ…">الاستعلام:
SET time_zone = '+00:00';
SELECT p.ID, p.post_title, FROM_UNIXTIME(pm.meta_value) AS starts_local
FROM wp_posts p
JOIN wp_postmeta pm ON pm.post_id = p.ID AND pm.meta_key = 'evcal_srow'
WHERE p.post_type = 'ajde_events'
AND p.post_status NOT IN ('trash', 'auto-draft')
ORDER BY pm.meta_value;
لو بادئة الجداول في موقعك ليست wp_، عدّلها في الاستعلام. شغّله من phpMyAdmin في لوحة الاستضافة، فهي متاحة عند معظم شركات الاستضافة المشتركة في المنطقة.
الفخ الثاني: صدّق repeat_intervals وليس الإعدادات
الفعالية المتكررة (Recurring Event) تخزّن قاعدة التكرار في عدة حقول:
- التكرار:
evcal_rep_freqوقيمهhourlyأوdailyأوweeklyأوmonthlyأوyearlyأوcustom. - الفاصل: عدد الوحدات بين كل موعد والتالي.
- الأسبوعي: الأيام المختارة في
evo_rep_WKwk، حيث 0 تعني الأحد. - الشهري حسب اليوم: في
evo_rep_WK، ورقم الأسبوع داخل الشهر فيevo_repeat_wom.
لكنها تخزّن أيضًا repeat_intervals، وهي قائمة بكل موعد ولّدته الإضافة فعلًا، على شكل أزواج [start, end] بنفس التوقيت الوهمي. هذه القائمة هي ما يظهر في التقويم للزوار.
إعادة بناء القاعدة من الإعدادات تنجح غالبًا، لكن ليس دائمًا. التكرار المخصص (custom) مجرد قائمة تواريخ، والتكرار كل ساعة لا يقابله شيء في معظم صيغ التقويم. لذلك وسّع أي قاعدة تعيد بناءها وقارن تواريخها بالقائمة، وعند الاختلاف اعتمد القائمة.
الفخ الثالث: عناوين الأماكن ليست في termmeta
تفاصيل الأماكن والمنظمين، من عنوان وإحداثيات وبيانات تواصل، لا توجد في wp_termmeta كما قد تتوقع. هي داخل خيار مُسلسَل (Serialized Option) واحد كبير اسمه evo_tax_meta، مفهرس بالتصنيف ثم رقم العنصر:
$meta = get_option( 'evo_tax_meta', array() );
$address = $meta['event_location'][ $term_id ]['location_address'] ?? '';
المواقع القديمة قد تحتوي أيضًا على خيار منفصل لكل عنصر باسم taxonomy_<term id>، ويقرؤه EventON كبديل احتياطي. افحص المكانين، وإلا ستصل أماكنك إلى الإضافة الجديدة بلا عناوين.
الفخ الرابع: أنواع الفعاليات في مجموعات مرقّمة
التصنيف event_type هو المجموعة الأولى من الأنواع. تفعيل مجموعات إضافية ينشئ event_type_2 وevent_type_3 وهكذا، ولكل منها رابط مستقل مثل /event-type_2/<slug>/.
قرّر مسبقًا أين ستذهب كل مجموعة في الإضافة الجديدة، وجهّز تحويلات 301 لروابطها كلها حتى لا تخسر ترتيبها في جوجل.
الروابط التي يجب أن تحصرها
الفعالية المفردة تكون افتراضيًا على /events/<slug>/، ويمكن تغيير ذلك من إعدادات EventON. صفحات التصنيفات تكون على:
/event-location/<slug>//event-organizer/<slug>//event-type/<slug>/بالإضافة إلى قاعدة مستقلة لكل مجموعة أنواع إضافية
سجّل الروابط الفعلية في موقعك قبل التبديل. إضافة مثل Redirection المجانية تكفي لإدارة التحويلات بعد ذلك.
قائمة الفحص قبل التبديل
- حوّل فعالية واحدة يدويًا باستخدام
gmdate()وقارن النتيجة بما يعرضه EventON في الواجهة. - احصر الفعاليات المتكررة، وقارن كل قاعدة أعدت بناءها بقائمة
repeat_intervals. - صدّر الخيار
evo_tax_metaمع المقالات، وإلا فقدت الأماكن عناوينها. - اعمل قائمة بكل تصنيفات
event_type*وقاعدة رابط كل منها. - خذ نسخة احتياطية (Backup) كاملة من قاعدة البيانات، وجرّب النقل على بيئة الاختبار (Staging) أولًا.
في Elementor + JetEngine: لو ناوي تبني تقويمك بنفسك بدل إضافة جاهزة، أنشئ نوع محتوى للفعاليات في JetEngine وخزّن وقت البداية في حقل تاريخ مع تفعيل خيار حفظه كطابع زمني. عند استيراد بيانات EventON حوّل القيم أولًا بـ gmdate() ثم خزّنها، حتى لا ينتقل الانزياح إلى موقعك الجديد.
اقرأ أيضًا
الأسئلة الشائعة
س: لماذا تتأخر مواعيد فعالياتي 3 ساعات بعد النقل من EventON؟
ج: لأن EventON يخزّن الساعة المحلية كأنها UTC، والإضافة الجديدة تضيف فارق منطقتك الزمنية عليها. اقرأ القيمة بـ gmdate() بدل wp_date().
س: أين أجد عنوان المكان في قاعدة بيانات EventON؟
ج: في الخيار evo_tax_meta داخل جدول wp_options، وأحيانًا في خيار قديم باسم taxonomy_<term id>.
س: هل أعتمد على إعدادات التكرار أم على repeat_intervals؟
ج: القائمة repeat_intervals هي الأدق لأنها المواعيد الفعلية المعروضة. استخدم الإعدادات فقط إذا طابقت تواريخها القائمة تمامًا.
س: هل ينطبق هذا على نسخة EventON المدفوعة؟
ج: حسب تحليل كاتب المقال الأصلي، تستخدم النسخة المدفوعة نفس نوع المحتوى والحقول، لكن راجع عينة من فعالياتك للتأكد.
الخلاصة
EventON لا يفقد بياناتك، لكنه يخزّنها بطريقة تخدع أي أداة نقل مستعجلة: توقيت وهمي، وقاعدة تكرار غير موثوقة دائمًا، وعناوين مخبأة في خيار واحد، وأنواع موزعة على عدة تصنيفات. جرّب فعالية واحدة يدويًا الأول، ولو طابقت، كمّل النقل وأنت مطمّن.
مرجع المقال (بالإنجليزية): Moving off EventON: its timestamps aren’t what they look like
المقال ده مش ترجمة حرفية: متكيّف للقارئ العربي ومضاف عليه سياق ووردبريس وElementor وJetEngine.



