Skip to content

MelisNewsletter

يحوّل صفحة CMS إلى نشرة بريدية مخصّصة ويسلّمها إلى مجموعات المشتركين، وهو الآن مُدار من واجهة إدارة خلفية أصلية مبنية على React. الحزمة melisplatform/melis-newsletter.

الغرض

يعيد MelisNewsletter استخدام نظام صفحات CMS بوصفه قالب النشرة البريدية: تُعرض الصفحة المُعلَّمة بالنوع NEWSLETTER بصيغة HTML، وتُخصَّص لكل مستلِم عبر رموز BB ([NAME]، [FIRSTNAME]، [EMAIL]، [UNSUBSCRIBELINK])، ثم تُرسَل إلى المشتركين و/أو المجموعات المحدَّدة عبر ناقل بريد قابل للتهيئة. يُنظَّم المشتركون في قائمة خاصة بكل موقع ويمكن تقسيمهم إلى مجموعات. تُؤرشَف كل عملية إرسال بلقطة HTML كاملة وسجلّ لكل مستلِم؛ ويتضمّن المنتج جاهزًا إضافة إلغاء الاشتراك في الواجهة الأمامية وتكاملًا كاملًا مع اللائحة العامة لحماية البيانات (GDPR).

في الإصدار v6 تُشحن الأداة بوصفها قالبًا (brick) أصليًا مبنيًا بالكامل على React ضمن واجهة الإدارة الخلفية /melis-react. أما منطق العمل (الخدمات، آلية الإرسال، GDPR، الجداول) فبقي دون تغيير؛ وانتقلت طبقة العرض وحدها إلى React، مُقدَّمة عبر طبقة JSON من نوع react-api تعرضها الوحدة.

تفعيلها

أضِف إلى config/melis.module.load.php:

php
return [
    'MelisNewsletter',
];

تتطلّب melis-core وmelis-cms؛ وتعتمد وظيفيًا أيضًا على melis-engine وmelis-front لعرض الصفحة وإضافة إلغاء الاشتراك. تظهر أداة React في القائمة فقط عند تفعيل الوحدة (اكتشاف القوالب النمطية عبر GET /melis/react-api/react-modules). وإزالة MelisNewsletter من melis.module.load.php تُخفي القالب (brick).

واجهة الإدارة الخلفية (React)

الشريط الجانبي الأيسر ← MelisMarketing ← Newsletter (fa fa-newspaper-o)، ومسار التركيب /melis-marketing/melis-newsletter-tool-config. تُفتح بوصفها أداة واحدة يحمل ترويستها العنوان Newsletters، والعنوان الفرعي "Subscribers, groups, history and send configuration" ومفتاح تبديل New / Old (أعلى اليمين). وNew هي واجهة React (الافتراضية)؛ أما Old فتعرض الأداة القديمة داخل إطار iframe (/melis/react-tool-page?key=melis_newsletter_tool_display).

بخلاف الأداة ذات التبويبات الفرعية المستضافة، تعرض Newsletter شاشاتها الأربع بوصفها تبويبات React خاصة بها:

التبويبالمحتوى
Subscribersبطاقات مؤشرات الأداء (Total / Active / Inactive)، بحث، مرشِّحات الحالة + الموقع، مدير الأعمدة، Import من CSV، Export، Add selection to group(s)، + New subscriber. الجدول: Status / Email / First name / Last name / Site / Groups مع تحرير/حذف لكل صف
Groupsبطاقات مؤشرات الأداء، بحث، مرشِّح الحالة، Export، + New group. الجدول: Status / Name / Created / Members (العدد) مع تحرير/حذف
Historyأرشيف للقراءة فقط. بطاقات مؤشرات الأداء (Sends / Sites / Today)، بحث، مرشِّح الموقع، Export. الجدول: Page / Site / Version / Sent on مع أيقونة عين لكل صف لعرض HTML المؤرشَف بدقّة
Configurationتهيئة Transport configuration العالمية الوحيدة لـ SMTP: Host / Username / Password (+ تأكيد). الحقل الفارغ = ناقل Melis الافتراضي

تبويب Subscribers في أداة Newsletter المبنية على React

فتح أو إنشاء مشترك أو مجموعة لا يفتح تبويبًا رئيسيًا جديدًا — بل يفتح محرّر السجل (SubscriberForm / GroupForm) في تبويب فرعي مستضاف أصلي (تنقّل تفصيلي، بمفتاح s-<id> / g-<id>). يحتوي نموذج المشترك على الاسم الأول/الأخير والبريد الإلكتروني والموقع ومفتاح تبديل Active والعضويات في المجموعات؛ ويحتوي نموذج المجموعة على الاسم ومفتاح تبديل Active وأعضاء المجموعة (إضافة/إزالة + منتقي المشتركين).

تبويب Groups في أداة Newsletter المبنية على React

تبويب History في أداة Newsletter المبنية على React

تبويب Configuration في أداة Newsletter المبنية على React

لأغراض الأمان، لا تُعاد كلمة مرور SMTP المخزّنة إلى المتصفّح مطلقًا — إذ تعرض الحقول عنصرًا نائبًا مُقنَّعًا، وتركها فارغة عند الحفظ يُبقي كلمة المرور الحالية.

إرسال نشرة بريدية

إجراء Send ليس تبويبًا. بل هو نافذة منبثقة (NewsletterSendModal) معروضة عبر window.__melisNewsletterSendModal، يعرضها محرّر صفحات React للصفحات من النوع NEWSLETTER. حدِّد موضوعًا، واختر مجموعات و/أو مشتركين، ونفِّذ Test إلى مشترك مختار أو عنوان بريد إلكتروني حرّ أولًا، ثم Send. عند النجاح يُطلِق حدث melis:newsletter-sent كي يتحدّث تبويب History الدائم. متغيّرات التخصيص في المحتوى: [NAME]، [FIRSTNAME]، [EMAIL]، [UNSUBSCRIBELINK]. انشُر الصفحة قبل الإرسال.

واجهة React البرمجية (React API)

توجد المسارات في config/react-api.php (مدمجة عبر MelisNewsletter\Module::getConfig())، وتُقدَّم بوصفها مسارات فرعية لجسر melis-react-api العام تحت /melis/react-api/newsletter. المتحكِّم MelisNewsletter\Controller\MelisReactApiNewsletterController؛ وعقد JSON هو { success, data, error }؛ ويحمل كل طلب X-Requested-With: XMLHttpRequest + بيانات الاعتماد. نقاط نهاية مختارة:

الطريقة والعنوان (بالنسبة إلى /melis/react-api/newsletter)الغرض
GET /subscribers · /subscribers/stats · /subscribers/:idقائمة بمفتاح keyset (search، active، site، group، sort، dir، after)، مؤشر الأداء، سجلّ واحد
POST /subscribers/save · /subscribers/importإنشاء/تحديث؛ استيراد مجمّع من CSV ← {imported,skipped,errors}
DELETE /subscribers/delete/:idحذف
GET /groups · /groups/stats · /groups/:id · /groups/:id/membersقائمة المجموعات، مؤشر الأداء، السجلّ، الأعضاء
POST /groups/save · /groups/:id/members/add · /groups/members/bulk-addحفظ؛ إضافة عضو؛ إسناد مجمّع لـ subscriberIds[] إلى groupIds[]
DELETE /groups/delete/:id · /groups/members/remove/:midحذف مجموعة؛ إزالة عضوية (mid = nlgu_id)
GET /history · /history/stats · /history/:idقائمة أرشيف الإرسال، مؤشر الأداء، HTML المؤرشَف لعملية إرسال واحدة
GET /config · POST /config/saveتهيئة SMTP (كلمة المرور لا تُعاد؛ فقط hasPassword) / حفظ
GET /send-options · POST /send · POST /testخيارات نافذة الإرسال؛ الإرسال؛ الإرسال التجريبي

يعيد متحكِّم React استخدام خدمة Laminas الخاصة بالوحدة (MelisNewsletterService) للعمليات الثقيلة — إذ يمرّ الإرسال/الاختبار عبر sendNewsletter() / testNewsletter() / testNewsletterCustomMail()، وتعكس عمليات التحقّق saveSubscriber / importFileValidator / saveConfig — بحيث يعيد مسار React إنتاج قواعد العمل القديمة نفسها بدقّة.

القدرات (الحقوق المتقدّمة)

مُعلَنة في config/react.capabilities.php تحت العقدة الحاملة للحقوق melis_newsletter_tools_section (وليس مفتاح البيان/المنطقة melis_newsletter_tool_display). شجرة لكل تبويب مع إجراء send واحد مشترك بين التبويبات، مُسطَّحة إلى سلاسل بنقاط:

melis_newsletter_tools_section
├─ action: send                              (Send / Test — the page-editor modal)
├─ tab subscribers: list · create · edit · delete · export
├─ tab groups:      list · create · edit · delete · export
├─ tab history:     list                     (read-only)
└─ tab config:      edit                     (SMTP transport)

يقرأها React عبر useCaps('melis_newsletter_tools_section').can('…') ويتحكّم في إظهار أزرار الإجراءات؛ وعلى جانب الخادم يُحرَس كل إجراء مُعدِّل (denyUnlessAccess() ثم denyUnlessCan()). كما يدمج react.capabilities.php إجراء newsletter تحت العقدة المشتركة meliscms_page بحيث يصبح زرّ Send في محرّر الصفحات قابلًا للتحكّم في Users ← Rights.

الخدمات الرئيسية

اسم الخدمة المستعارالدور
MelisNewsletterServiceالخدمة المركزية للمشتركين والمجموعات والإرسال/الاختبار والأرشفة والتهيئة. تُطلِق أحداث *_start / *_end.
MelisNewsletterGdprAutoDeleteServiceيُنفِّذ MelisCoreGdprAutoDeleteInterface؛ يقود سير عمل التحذير/الحذف المجدول لـ GDPR للمشتركين الراكدين.

الأسماء المستعارة لبوابات الجداول (table gateway): MelisNewsletterSubscribersTable، MelisNewsletterGroupsTable، MelisNewsletterGroupsPeopleTable، MelisNewsletterArchiveTable، MelisNewsletterRecipientsTable، MelisNewsletterConfigTable.

آلية الإرسال

MelisNewsletterService::sendNewsletter($pageId, $subscribers, $groups, $mailSubject):

  1. تحديد المستلمين — المشتركون الصريحون + أعضاء المجموعات عبر getSubscribersInGroup()، مُرشَّحون إلى النشِطين فقط، ومُزال منهم التكرار.
  2. عرض المحتوى — تُجلَب صفحة CMS بصيغة HTML؛ وتُعاد كتابة href/src النسبية إلى عناوين URL مطلقة.
  3. التخصيص — تُستبدَل رموز BB لكل مستلِم؛ ويحمل [UNSUBSCRIBELINK] الرمز المُجزّأ (hashed token).
  4. الإرسال — عبر ناقل SMTP المُهيّأ أو الافتراضي للمنصّة.
  5. الأرشفة — صفّ nlan_* واحد لكل عملية إرسال (الموقع، الصفحة، الإصدار، HTML كامل، تاريخ الإرسال) وصفّ nlus_* واحد لكل مستلِم.

الإرسال التجريبي (testNewsletter() / testNewsletterCustomMail()) يسلّم إلى مشترك واحد أو بريد إلكتروني عشوائي دون أرشفة، وهو مطلوب قبل أن يُفتَح الإرسال الحقيقي.

الواجهة الأمامية

الإضافةمفتاح التهيئةالوصف
MelisNewsletterUnsubscribePluginmelisnewsletter / MelisNewsletterUnsubscribePluginضَعها على صفحة unsubscribe. تقرأ الرمز ?s={hashed_id} المُضمَّن في [UNSUBSCRIBELINK]، وتستدعي deactivateSubscriberById()، وتعرض رسالة نجاح/فشل. تعرض إعداد unsubscribe_data_salt المستخدَم في تجزئة الرمز.

العروض: plugins/unsubscribe.phtml + unsubscribe-modal-form.phtml.

تكامل GDPR

يربط إطار GDPR الخاص بـ MelisCore لكلٍّ من السير عند الطلب والمجدول:

  • عند الطلب: يعثر كلٌّ من MelisNewsletterGdprUserInfoListener و…UserExtractListener و…UserDeleteListener على بيانات مشترك شخص ما ويصدّرها ويحذفها عند الطلب. الأعمدة: nlu_firstname، nlu_name، nlu_email، nlu_date_creation (مُعلَنة في config/app.gdpr.php).
  • الحذف التلقائي المجدول: MelisNewsletterGdprAutoDeleteService مع تسعة مستمعين يغطّون تسجيل الوحدة، وإعلان وسم GDPR، وبناء قائمة التحذير، ورسائل التحذير، والحذف النهائي للمشتركين غير النشطين الذين لا يستجيبون.

جداول قاعدة البيانات

الجدول (الاسم المستعار ← بادئة الأعمدة)يحتوي
MelisNewsletterSubscribersTable (nlu_*)صفوف المشتركين لكل موقع: البريد الإلكتروني، الاسم الأول/الأخير، الحالة، تاريخ الإنشاء
MelisNewsletterGroupsTable (nlg_*)تعريفات المجموعات: الاسم، الحالة، تاريخ الإنشاء
MelisNewsletterGroupsPeopleTable (nlgu_*)رابط العضوية بين المشترك ↔ المجموعة
MelisNewsletterArchiveTable (nlan_*)أرشيف لكل إرسال: الموقع، الصفحة، الإصدار، جسم HTML الكامل، تاريخ الإرسال
MelisNewsletterRecipientsTable (nlus_*)سجلّ الإرسال لكل مستلِم: لقطة الاسم/الاسم الأول/البريد الإلكتروني، مفتاح خارجي للأرشيف
MelisNewsletterConfigTable (nlc_*)تهيئة ناقل SMTP لكل موقع: المضيف، اسم المستخدم، كلمة المرور

مثال

php
$nl = $serviceManager->get('MelisNewsletterService');

// Subscriber / group management (same service the react-api reuses)
$nl->saveSubscriber($data, $id);           // $id null → create
$nl->deactivateSubscriberById($id);
$nl->saveGroup($data, $id);
$nl->getSubscribersInGroup($grpId);

// Send flow
$nl->testNewsletter($pageId, $subId, $subject);
$nl->sendNewsletter($pageId, $subscribers, $groups, $subject);

// History & config
$nl->getNewsletterRecipients($archiveId);
$nl->saveNewsletterConfig($cfg);

الملفات الرئيسية

المجالالمسار
مسارات React API + المتحكِّم القابل للاستدعاءvendor/melisplatform/melis-newsletter/config/react-api.php
قدرات React (بمفتاح melis_newsletter_tools_section)vendor/melisplatform/melis-newsletter/config/react.capabilities.php
متحكِّم React API (يعيد استخدام MelisNewsletterService)vendor/melisplatform/melis-newsletter/src/Controller/MelisReactApiNewsletterController.php
قالب React (بناء Vite) + البيانvendor/melisplatform/melis-newsletter/public/ui-react/brick.js · brick.manifest.json
تهيئة الوحدة (الخدمات، بوابات الجداول، المتحكِّمات، الإضافة)vendor/melisplatform/melis-newsletter/config/module.config.php
الخدمة الرئيسيةvendor/melisplatform/melis-newsletter/src/Service/MelisNewsletterService.php
خدمة الحذف التلقائي لـ GDPRvendor/melisplatform/melis-newsletter/src/Service/MelisNewsletterGdprAutoDeleteService.php
إضافة إلغاء الاشتراك في الواجهة الأماميةvendor/melisplatform/melis-newsletter/src/Controller/Plugin/MelisNewsletterUnsubscribePlugin.php
بوابات الجداولvendor/melisplatform/melis-newsletter/src/Model/Tables/
تثبيت قاعدة البيانات + الترحيلاتvendor/melisplatform/melis-newsletter/install/dbdeploy/

انظر أيضًا: melis-core، melis-cms، melis-front، melis-engine