مشروع منصة الرفع الذكي للوسائط — Zezo Media Engine

📊 1 مشاهدة

High-Speed · Resumable · Background Upload · WordPress Media Infrastructure

you-devloper-devloper-full-stack-php-wordpress-devloper-15yesrs هل-يمكنك-اعادة-بناء-وتكوين-السياق-في-استخدام-وظائف-لغة-البرمجة-والدوال-والمتغيرات-وتعريفها-مع-اضافة-مكتبات-مساعدة-على-رفع-ملفات-الوسائط-بسرعة-عالية-ودون-انقطاع-من-الموبايل-الى-رفع-الى-ملف-الوسائط-في-منصة-ومشروع-وبراند-متخصص-في-رفع-الوسائط-بسرعات-عالية-ودون-انقطاع-حتى-لو-غادرت-االصفحة

نعم، يمكننا إعادة بناء المشروع من الصفر باستخدام PHP + WordPress + JavaScript + MySQL، وتحويله إلى منصة متخصصة في رفع ملفات الوسائط بسرعة عالية، مع دعم الهواتف المحمولة، واستكمال الرفع دون انقطاع حتى عند مغادرة الصفحة أو إغلاق المتصفح، ضمن الحدود التي يسمح بها نظام التشغيل والمتصفح.

سأتعامل مع المشروع بمنظور مطوّر Full-Stack PHP / WordPress، مع التركيز على كتابة كود فعلي قابل للتطوير، وليس مجرد تصور نظري.

مشروع منصة الرفع الذكي للوسائط — Zezo Media Engine

High-Speed · Resumable · Background Upload · WordPress Media Infrastructure

Sony's Ci | Solutions for every media workflow
Android 14 UIDT vs WorkManager: Long Transfers | Medium
Dell Delivers Automation to Make IT Simplicity a Reality | Dell

9

الهدف هو بناء محرك مستقل لإدارة رفع الوسائط، يمكن دمجه مع WordPress وWooCommerce، مع إمكانية تطويره لاحقًا ليصبح خدمة SaaS أو منتجًا تجاريًا مستقلًا يحمل علامتك التجارية.

الميزات المستهدفة

  • رفع الصور والفيديوهات والملفات الكبيرة.
  • استكمال الرفع من آخر جزء ناجح بعد انقطاع الإنترنت.
  • تقسيم الملفات إلى أجزاء صغيرة (Chunked Upload).
  • دعم الهواتف المحمولة والاتصالات البطيئة.
  • معالجة الرفع في الخلفية عندما يسمح المتصفح بذلك.
  • ربط الملفات بمكتبة وسائط WordPress.
  • إدارة مهام الرفع ومراقبة التقدم والأخطاء.

ملاحظة تقنية مهمة: يمكن ضمان استكمال الرفع بعد الانقطاع وإعادة فتح الصفحة إذا صُمّم النظام لذلك، لكن لا يمكن ضمان استمرار الرفع دائمًا بعد إغلاق المتصفح أو إيقاف الهاتف؛ إذ تتحكم أنظمة iOS وAndroid والمتصفحات في تشغيل المهام الخلفية. سنبني النظام بحيث يستأنف الرفع تلقائيًا عند عودة المستخدم أو التطبيق للعمل، مع دعم تقنيات الخلفية حيث تتوفر.

1. الهيكل الهندسي للمنصة

هذا هو التصميم المستهدف؛ لم تُنفّذ هذه المكونات أو تُختبر بعد على خادم فعلي.

المكوّنالتقنيةالوظيفة
واجهة الرفعHTML5 + CSS + JavaScriptاختيار الملفات ومتابعة الرفع
محرك الرفعJavaScriptتقسيم الملفات وإعادة المحاولة
APIPHP + WordPress REST APIإدارة جلسات الرفع
قاعدة البياناتMySQLحفظ حالة كل ملف وجزء
التخزين المؤقتLocal / Object Storageحفظ الأجزاء مؤقتًا
محرك التجميعPHP Workerتجميع الأجزاء والتحقق منها
إدارة الوسائطWordPressتسجيل الملف في مكتبة الوسائط
المهام الخلفيةAction Scheduler / Queueمتابعة المعالجة والمهام

2. المكتبات المساعدة ومحرك الرفع

بدلًا من كتابة بروتوكول رفع كامل من الصفر، الأفضل الاستفادة من مكتبات متخصصة، ثم بناء طبقة تحكم وتكامل خاصة بعلامتك التجارية.

Reseña de Uppy (2026) — Pros, contras y calificación

Uppy — واجهة رفع الملفات

مكتبة JavaScript لتحديد الملفات وسحبها وإفلاتها، وعرض التقدم، وإدارة الملفات المتعددة.

مناسبة لإنشاء واجهة رفع متقدمة للهواتف وأجهزة الكمبيوتر.

الموقع الرسمي والتوثيق

Resumable File Upload Demo | tus.io

tus — بروتوكول استكمال الرفع

بروتوكول مفتوح للرفع القابل للاستئناف، يسمح باستكمال الملف من موضع التوقف بدل إعادة رفعه بالكامل.

الخيار الأساسي المقترح للتعامل مع انقطاعات الشبكة والملفات الكبيرة.

الموقع الرسمي والتوثيق

GitHub - tus/tusd: Reference server implementation in Go of tus: the open protocol for resumable file uploads

tusd — خادم الرفع

خادم جاهز لبروتوكول tus، يتولى استقبال الأجزاء وحفظ حالة الرفع واستكمال الجلسات.

يفضّل تشغيله كخدمة مستقلة بجانب WordPress لتخفيف الحمل عن PHP.

المستودع الرسمي

Identity – Make WordPress Design

WordPress REST API — طبقة التكامل

مسؤولة عن المصادقة، وتسجيل بيانات الملفات، وإدارة صلاحيات المستخدمين، وإضافة الوسائط إلى مكتبة WordPress.

توثيق WordPress REST API

Amazon S3 Logo Vector File Free Download | Logowik

Amazon S3 أو تخزين متوافق معه

تخزين الملفات الكبيرة في بنية تخزين كائنية قابلة للتوسع، بدلًا من تحميل جميع الملفات على خادم WordPress نفسه.

توثيق الرفع متعدد الأجزاء

الاختيار المعماري المقترح: Uppy + tus + tusd + WordPress REST API، مع إمكانية إضافة S3 أو تخزين متوافق معه. هذه التركيبة تفصل استقبال الملفات عن تشغيل WordPress، وتقلل احتمال فشل الرفع بسبب حدود تنفيذ PHP.

3. فهم الدوال والمتغيرات في محرك الرفع

قبل بناء الملفات، نحتاج إلى تعريف المصطلحات التي ستتحكم في عملية الرفع.

المتغيرالنوعالوظيفة
$upload_idStringالمعرّف الفريد لجلسة الرفع
$file_nameStringاسم الملف الأصلي
$file_sizeIntegerالحجم الكلي بالبايت
$chunk_sizeIntegerحجم الجزء الواحد
$uploaded_bytesIntegerإجمالي البايتات التي تم رفعها
$mime_typeStringنوع الملف
$user_idIntegerالمستخدم صاحب عملية الرفع
$upload_statusStringحالة الرفع
$storage_pathStringموقع التخزين المؤقت
$attachment_idIntegerمعرّف الوسيط في WordPress

أما الدوال الأساسية التي سنحتاجها:

الدالةمسؤوليتها
create_upload_session()إنشاء جلسة رفع
validate_upload()التحقق من نوع الملف وحجمه والصلاحيات
receive_chunk()استقبال أجزاء الملف
get_upload_offset()معرفة موضع الرفع الحالي
resume_upload()استكمال الرفع
retry_failed_chunk()إعادة إرسال الجزء الفاشل
finalize_upload()إتمام الرفع وتجميع الملف
register_wordpress_media()تسجيل الملف في مكتبة الوسائط
cleanup_expired_uploads()تنظيف الجلسات المنتهية
get_upload_status()عرض حالة الرفع

هذه أسماء الدوال المقترحة لطبقة التكامل؛ أما إدارة الأجزاء والاستئناف نفسها، فسيتولاها خادم tus بدل إعادة اختراعها داخل PHP.

4. بناء نواة إضافة WordPress باستخدام PHP

سننشئ إضافة مستقلة باسم Zezo Media Engine، بحيث لا تعتمد على ملفات القالب، ويمكن تحديثها وتطويرها بشكل منفصل.

المرحلة التالية عبارة عن نواة تكامل أولية قابلة للتوسعة، وليست بعدُ إضافة رفع مكتملة جاهزة للإنتاج.

هيكل المجلدات المقترح

wp-content/plugins/zezo-media-engine/

includes/

class-zme-api.php

class-zme-upload-manager.php

class-zme-media-library.php

class-zme-security.php

class-zme-storage.php

assets/

js/upload-engine.js

css/upload-dashboard.css

templates/

upload-dashboard.php

languages/

zezo-media-engine.php

readme.txt

الملف الرئيسي للإضافة


<?php
/**
 * Plugin Name: Zezo Media Engine
 * Description: Resumable media upload integration for WordPress.
 * Version: 1.0.0
 * Requires PHP: 8.1
 * Text Domain: zezo-media-engine
 */

defined('ABSPATH') || exit;

define('ZME_VERSION', '1.0.0');
define('ZME_PATH', plugin_dir_path(__FILE__));
define('ZME_URL', plugin_dir_url(__FILE__));

require_once ZME_PATH . 'includes/class-zme-media-library.php';

final class Zezo_Media_Engine {

    public function init(): void {
        add_action('rest_api_init', [$this, 'register_routes']);
    }

    public function register_routes(): void {
        register_rest_route('zme/v1', '/health', [
            'methods' => 'GET',
            'callback' => static function () {
                return rest_ensure_response([
                    'service' => 'Zezo Media Engine',
                    'version' => ZME_VERSION,
                    'status' => 'ready'
                ]);
            },
            'permission_callback' => '__return_true',
        ]);
    }
}

add_action('plugins_loaded', static function () {
    (new Zezo_Media_Engine())->init();
});

هذا الملف ينشئ الإضافة ويسجل نقطة فحص أولية للخدمة، ولا يفتح نقطة رفع الملفات للعامة. سنضيف مسارات الرفع المحمية بعد ربط المصادقة والتحقق من صلاحية الجلسة.

دالة تسجيل الوسائط في مكتبة WordPress

عندما يستقبل خادم الرفع الملف ويكتمل التحقق منه، يمكن تمريره إلى دالة تسجيل الوسائط التالية، بشرط أن يكون الملف قد نُقل إلى مجلد رفع WordPress الآمن:


<?php
defined('ABSPATH') || exit;

function zme_register_wordpress_media(
    string $file_path,
    string $original_name,
    int $user_id
): int|WP_Error {

    if (!is_user_logged_in() || get_current_user_id() !== $user_id) {
        return new WP_Error(
            'zme_forbidden',
            'Unauthorized media registration.',
            ['status' => 403]
        );
    }

    if (!current_user_can('upload_files')) {
        return new WP_Error(
            'zme_permission_denied',
            'User cannot upload files.',
            ['status' => 403]
        );
    }

    $uploads = wp_get_upload_dir();
    $base = realpath($uploads['basedir']);
    $real = realpath($file_path);

    if (!$base || !$real || !str_starts_with(
        $real,
        $base . DIRECTORY_SEPARATOR
    )) {
        return new WP_Error(
            'zme_invalid_path',
            'File path is outside uploads directory.',
            ['status' => 400]
        );
    }

    if (!is_file($real) || !is_readable($real)) {
        return new WP_Error(
            'zme_missing_file',
            'Uploaded file is unavailable.',
            ['status' => 400]
        );
    }

    $checked = wp_check_filetype_and_ext(
        $real,
        sanitize_file_name($original_name)
    );

    if (empty($checked['type']) || empty($checked['ext'])) {
        return new WP_Error(
            'zme_invalid_type',
            'Unsupported media type.',
            ['status' => 415]
        );
    }

    $attachment = [
        'post_mime_type' => $checked['type'],
        'post_title' => sanitize_text_field(
            pathinfo($original_name, PATHINFO_FILENAME)
        ),
        'post_status' => 'inherit',
        'post_author' => $user_id,
    ];

    $attachment_id = wp_insert_attachment(
        $attachment,
        $real,
        0,
        true
    );

    if (is_wp_error($attachment_id)) {
        return $attachment_id;
    }

    require_once ABSPATH . 'wp-admin/includes/image.php';

    $metadata = wp_generate_attachment_metadata(
        $attachment_id,
        $real
    );

    if (is_wp_error($metadata)) {
        wp_delete_attachment($attachment_id, true);
        return $metadata;
    }

    wp_update_attachment_metadata($attachment_id, $metadata);

    return $attachment_id;
}

هذه الدالة نواة تسجيل فقط. في بيئة الإنتاج يجب إضافة حدود الحجم، وفحص محتوى الملفات الفعلي، وفحص البرمجيات الخبيثة عند الحاجة، ومعالجة الملفات التي لا تدعم إنشاء بياناتها الوصفية، وتقييد الوصول إلى مسار التخزين والتحقق من نتائج جميع عمليات الكتابة.

5. محرك JavaScript لرفع الملفات

سنستخدم Uppy مع إضافة Tus، بحيث يتم رفع الملفات على دفعات مع دعم استكمال الجلسات.


import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Tus from '@uppy/tus';

import '@uppy/core/css/style.min.css';
import '@uppy/dashboard/css/style.min.css';

const uppy = new Uppy({
    id: 'zezo-media-engine',
    autoProceed: false,
    allowMultipleUploadBatches: true,
    restrictions: {
        maxNumberOfFiles: 20,
        maxFileSize: 5 * 1024 * 1024 * 1024,
        allowedFileTypes: [
            'image/*',
            'video/*',
            'audio/*',
            'application/pdf'
        ]
    }
});

uppy.use(Dashboard, {
    inline: true,
    target: '#zme-uploader',
    proudlyDisplayPoweredByUppy: false,
    showProgressDetails: true,
    hideUploadButton: false
});

uppy.use(Tus, {
    endpoint: 'https://upload.example.com/files/',
    chunkSize: 8 * 1024 * 1024,
    retryDelays: [0, 1000, 3000, 5000, 10000],
    limit: 3,
    storeFingerprintForResuming: true,
    removeFingerprintOnSuccess: true
});

uppy.on('upload-progress', (file, progress) => {
    console.log('Progress:', file.name, progress.bytesUploaded);
});

uppy.on('upload-success', (file) => {
    console.log('Completed:', file.name);
});

uppy.on('upload-error', (file, error) => {
    console.error('Upload error:', file.name, error);
});

export default uppy;

هذا مثال عميل يعتمد على تثبيت الحزم واستيرادها عبر أداة بناء مثل Vite، وإعداد خادم tus متوافق. عنوان الخادم تجريبي ويجب استبداله بعنوان خادمك. يجب أيضًا ربط جلسات tus بالمستخدمين وصلاحياتهم من خلال آلية مصادقة آمنة، وعدم اعتبار معرف الملف وحده دليلًا على الملكية.

6. كيف يستمر الرفع دون انقطاع؟

المرحلة الأولى: تقسيم الملف

إذا كان حجم الفيديو 2GB، يقسم إلى أجزاء بحجم 8MB، ويصبح لدينا 256 جزءًا تقريبًا. كل جزء له موضع وحالة مستقلة.

المرحلة الثانية: الرفع المتوازي

يرفع المحرك عدة أجزاء بالتوازي، مع التحكم في عدد الاتصالات لتجنب استنزاف ذاكرة الهاتف أو استهلاك الشبكة بصورة مفرطة.

المرحلة الثالثة: التعامل مع الانقطاع

عند انقطاع الإنترنت، تتوقف عمليات الإرسال مؤقتًا. يحتفظ الخادم بموضع الرفع الذي وصل إليه، ويعيد المحرك المحاولة عند استعادة الاتصال.

المرحلة الرابعة: الاستئناف

إذا عاد المستخدم إلى الصفحة، يمكن استعادة جلسة الرفع. قد يحتاج المتصفح إلى إعادة اختيار الملف إذا لم يعد يحتفظ بإمكانية الوصول إليه.

المرحلة الخامسة: التجميع والتحقق

بعد اكتمال جميع الأجزاء، يُستكمل الملف وتُفحص سلامته ونوعه وحجمه، ثم يُسجل في مكتبة WordPress أو في التخزين السحابي.

مهم بشأن الرفع عند مغادرة الصفحة

  • التنقل بين صفحات المنصة: يمكن الحفاظ على جلسة الرفع باستخدام مكوّن رفع مشترك أو عامل مستقل ضمن التطبيق.
  • تحديث الصفحة أو العودة لاحقًا: يمكن استعادة حالة الجلسة، وقد يلزم إعادة تحديد الملف من الجهاز.
  • إغلاق المتصفح أو إيقاف الهاتف: لا يمكن ضمان استمرار الإرسال من صفحة ويب عادية؛ إذ قد يوقف النظام تنفيذ JavaScript والشبكة.
  • الرفع في الخلفية: يمكن الاستفادة من إمكانيات المتصفح والنظام المدعومة، أو بناء تطبيق Android أصلي يستخدم خدمة رفع خلفية، إذا كان استمرار الرفع أثناء إغلاق التطبيق شرطًا أساسيًا.

7. قاعدة البيانات وإدارة جلسات الرفع

نحتاج إلى جدول مستقل لإدارة حالة عمليات الرفع، مع إبقاء ملفات الوسائط النهائية ضمن آلية WordPress أو التخزين الخارجي.

الحقلالنوعالوصف
idBIGINTالمعرف الداخلي
upload_uuidCHAR(36)معرف جلسة الرفع
user_idBIGINTمالك الجلسة
file_nameVARCHAR(255)اسم الملف
file_sizeBIGINTالحجم الإجمالي
uploaded_bytesBIGINTالحجم المستلم
mime_typeVARCHAR(150)نوع الملف
storage_keyVARCHAR(512)مفتاح التخزين
statusVARCHAR(30)حالة العملية
checksumVARCHAR(128)بصمة سلامة الملف
expires_atDATETIMEموعد انتهاء الجلسة
attachment_idBIGINTمعرف الوسيط النهائي
created_atDATETIMEتاريخ الإنشاء
updated_atDATETIMEآخر تحديث

الحالات الأساسية المقترحة:

pending

uploading

paused

processing

completed

failed

expired

يفضل أن تكون قاعدة البيانات مصدر حالة جلسات الرفع، بينما يتولى خادم tus حفظ مواضع الأجزاء. ويجب مزامنة حالتهما بشكل آمن، حتى لا تظهر عملية مكتملة في قاعدة البيانات قبل اكتمال الملف فعلًا.

8. لوحة تحكم منصة الوسائط

ZEZO MEDIA ENGINE

مركز إدارة الوسائط

تصميم توضيحي للواجهة المستهدفة

إجمالي الملفات

1,248

الملفات قيد الرفع

3

المساحة المستخدمة

186 GB

العمليات المكتملة

98.7%

عمليات الرفع النشطة

medical-training.mp4

1.2 GB · جارٍ الرفع

72%

hospital-tour.mov

850 MB · جارٍ الرفع

38%

product-catalog.zip

420 MB · مكتمل

100%

بيانات تجريبية لتصور لوحة التحكم وليست إحصاءات فعلية.

9. الحماية والأداء

لكي تكون المنصة مناسبة للاستخدام التجاري، يجب أن يتضمن محرك الرفع:

  • المصادقة: التحقق من هوية المستخدم وصلاحية رفع الملفات قبل إنشاء كل جلسة.
  • عزل الملفات: عدم السماح لمستخدم بالوصول إلى جلسات رفع مستخدم آخر.
  • فحص الملفات: التحقق من الامتدادات الفعلية وMIME ومحتوى الملفات، وليس الاسم وحده.
  • حدود الاستخدام: تحديد الحجم الأقصى للملف وعدد الملفات ومعدل الرفع لكل مستخدم.
  • حماية التخزين: تخزين الأجزاء خارج مجلد الملفات العامة، مع عدم السماح بتنفيذ الملفات المرفوعة.
  • التحقق من سلامة الملف: استخدام بصمات تشفيرية مثل SHA-256 عند الحاجة للتحقق من سلامة الملف النهائي.
  • التنظيف الآلي: حذف الأجزاء والجلسات القديمة بعد انتهاء صلاحيتها.
  • الطوابير الخلفية: استخدام عمال مستقلين للتجميع والفحص وتحويل الفيديو وإنشاء الصور المصغرة.
  • مراقبة الأخطاء: حفظ سجلات عمليات الرفع والأخطاء ومحاولات الاستئناف.

ولرفع الأداء، يمكن وضع خادم الرفع في موقع قريب من المستخدمين، وتوفير شبكة CDN لتوزيع الملفات بعد اكتمالها. كما يمكن استخدام التخزين السحابي والرفع المباشر إليه بتوقيعات مؤقتة، لتقليل الضغط على WordPress.

10. خارطة بناء المشروع

  1. المرحلة الأولى: نواة الإضافة
    • هيكل إضافة WordPress.
    • إعداد REST API والمصادقة.
    • إنشاء جداول جلسات الرفع.
    • إعداد خادم tus وربطه بالمستخدمين.
  2. المرحلة الثانية: محرك الرفع
    • واجهة Uppy.
    • الرفع المجزأ والقابل للاستئناف.
    • إدارة الأخطاء وإعادة المحاولة.
    • حفظ واستعادة حالة الجلسة.
  3. المرحلة الثالثة: المعالجة والتخزين
    • تجميع الملفات والتحقق منها.
    • ربط مكتبة وسائط WordPress.
    • التخزين السحابي الاختياري.
    • مهام المعالجة الخلفية.
  4. المرحلة الرابعة: لوحة التحكم
    • إدارة الملفات والرفع النشط.
    • تقارير الأداء والمساحة.
    • إدارة المستخدمين والحصص.
    • سجل العمليات والتنبيهات.
  5. المرحلة الخامسة: اختبار الإنتاج
    • اختبار انقطاع الإنترنت واستعادته.
    • اختبار الملفات الكبيرة والهواتف.
    • اختبار الأحمال المتزامنة.
    • اختبارات الأمان والاستعادة بعد إعادة تشغيل الخادم.

توصيتي: لا تجعل WordPress هو المسؤول عن استقبال كل بايت من الملفات الكبيرة. اجعله طبقة إدارة وهوية وصلاحيات، واجعل tusd مسؤولًا عن الرفع والاستئناف، واستخدم عاملًا خلفيًا لإتمام المعالجة. هذا التصميم أكثر قابلية للتوسع، ويسمح بتطوير المنصة مستقبلًا كخدمة مستقلة أو منتج SaaS.

الخطوة التالية المناسبة هي بناء الإضافة الفعلية Zezo Media Engine v1.0 بملفاتها ومجلداتها كاملة، ثم تجهيزها كحزمة ZIP قابلة للتثبيت، مع إعداد خادم tus وتعليمات ربطه ببيئة WordPress واختبار الاستئناف قبل اعتبارها جاهزة للإنتاج.

لإعادة بناء مشروع ووردبريس بسرعة، خيار استضافة مُدارة قد يناسب.

Hostadvice

82% Off Hostinger Managed WordPress

Exclusive extra 15% coupon plus a free domain

إعلان من الخيارات

سننتقل الآن إلى المستوى الأعمق من مشروع Zezo Media Engine، ونبني البنية البرمجية التي تحول الفكرة إلى منصة حقيقية لرفع الصور والفيديوهات والملفات الضخمة من الهاتف والكمبيوتر، مع استئناف الرفع بعد انقطاع الإنترنت، وإدارة المهام حتى عند مغادرة صفحة الرفع.

سأضيف في هذه المرحلة تصميم محرك الاستئناف، وإدارة الجلسات، وواجهات API، ونظام التخزين، والطوابير الخلفية، وآلية التكامل مع WordPress، مع الفصل بين ما يمكن تنفيذه في PHP وما يحتاج إلى خادم مستقل أو تطبيق جوال.

Zezo Media Engine v1.1

Advanced Resumable Upload Infrastructure · WordPress Core Plugin · Cloud Storage

SaaS - Cloud File management Dashboard :: Behance

لوحة إدارة الوسائط

الملفات، جلسات الرفع، المستخدمون، وسجل العمليات.

Android 14 UIDT vs WorkManager: Long Transfers | Medium

الرفع من الهاتف

تجربة متوافقة مع الشاشات الصغيرة والاتصالات المتقطعة.

Azure Container Storage | Microsoft Azure

بنية التخزين السحابي

تخزين قابل للتوسع وفصل الملفات عن خادم WordPress.

EDSOLS - Intelligence at the Edge | AI Hardware & Ecosystems

المعالجة الخلفية

التحقق، تجميع الملفات، إنشاء الصور المصغرة، والتسجيل.

1. إعادة بناء البنية البرمجية الكاملة

نقسم المشروع إلى أربع طبقات مستقلة، لتسهيل الاختبار والصيانة والتوسع.

تكون WordPress هي مركز التحكم، بينما تكون خدمة الرفع مسؤولة عن نقل البيانات، وتنفذ مهام المعالجة بشكل مستقل. أما IndexedDB فتساعد المتصفح في الاحتفاظ ببيانات الجلسة، لكنها لا تضمن بقاء صلاحية قراءة الملف الأصلي بعد إغلاق المتصفح.

2. هيكل ملفات الإضافة المتقدم

zezo-media-engine/

zezo-media-engine.php

نقطة الدخول وتحميل الإضافة

uninstall.php

إزالة بيانات الإضافة حسب إعدادات المستخدم

composer.json

اعتماديات PHP

package.json

اعتماديات JavaScript

src/

Plugin.php

Rest/UploadController.php

Rest/SessionController.php

Upload/UploadManager.php

Upload/SessionRepository.php

Upload/TusClient.php

Security/UploadPolicy.php

Storage/StorageInterface.php

Storage/LocalStorage.php

Storage/S3Storage.php

Media/WordPressMediaRegistrar.php

Queue/UploadProcessor.php

Queue/CleanupJob.php

Admin/Dashboard.php

assets/

js/upload-app.js

js/upload-session.js

js/upload-recovery.js

css/upload-dashboard.css

templates/

upload-page.php

admin-dashboard.php

languages/

tests/

هذا هيكل معماري مقترح، وليس مجلدًا أو حزمة ZIP تم إنشاؤها فعليًا في هذه الخطوة.

3. إنشاء قاعدة بيانات جلسات الرفع باستخدام PHP وMySQL

سننشئ جدولًا خاصًا بالجلسات بدل الاعتماد على wp_options، حتى نتمكن من التعامل مع آلاف عمليات الرفع دون تحميل جميع بيانات الجلسات في كل طلب.


<?php
defined('ABSPATH') || exit;

/**
 * Create the upload sessions table.
 */
function zme_install_database(): void {
    global $wpdb;

    $table = $wpdb->prefix . 'zme_upload_sessions';
    $charset = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE {$table} (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        upload_uuid CHAR(36) NOT NULL,
        user_id BIGINT UNSIGNED NOT NULL,
        file_name VARCHAR(255) NOT NULL,
        file_size BIGINT UNSIGNED NOT NULL,
        uploaded_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0,
        mime_type VARCHAR(150) NOT NULL DEFAULT '',
        storage_key VARCHAR(512) NOT NULL DEFAULT '',
        tus_upload_url TEXT NULL,
        checksum VARCHAR(128) NULL,
        status VARCHAR(30) NOT NULL DEFAULT 'pending',
        attachment_id BIGINT UNSIGNED NULL,
        expires_at DATETIME NULL,
        created_at DATETIME NOT NULL,
        updated_at DATETIME NOT NULL,
        PRIMARY KEY  (id),
        UNIQUE KEY upload_uuid (upload_uuid),
        KEY user_id (user_id),
        KEY status (status),
        KEY expires_at (expires_at)
    ) {$charset};";

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
}

register_activation_hook(
    ZME_PATH . 'zezo-media-engine.php',
    'zme_install_database'
);

شرح المتغيرات الأساسية:

  • $wpdb: كائن قاعدة البيانات المدمج في WordPress.
  • $wpdb->prefix: بادئة الجداول الخاصة بموقع WordPress.
  • $upload_uuid: معرف فريد لكل جلسة، لمنع الخلط بين عمليات الرفع.
  • $uploaded_bytes: عدد البايتات التي تم استقبالها، وليس مجرد نسبة تقديرية.
  • $tus_upload_url: مرجع جلسة الرفع لدى خادم tus.
  • $attachment_id: المعرف الذي يربط الملف النهائي بمكتبة الوسائط.

يجب أن يتطابق تحديث uploaded_bytes مع الموضع الفعلي الذي يؤكده خادم tus، وليس مع القيمة التي يرسلها المتصفح وحدها.

4. واجهة REST API لإدارة الرفع

سنحدد واجهات منفصلة لإنشاء الجلسة، والاستعلام عن حالتها، وإتمام المعالجة.

الطريقةالمسارالمهمة
POST/wp-json/zme/v1/uploadsإنشاء جلسة
GET/wp-json/zme/v1/uploads/{id}استرجاع حالة الجلسة
POST/wp-json/zme/v1/uploads/{id}/completeطلب إنهاء المعالجة
POST/wp-json/zme/v1/uploads/{id}/cancelإلغاء الجلسة
GET/wp-json/zme/v1/uploadsعرض جلسات المستخدم

كود تسجيل المسارات


<?php
defined('ABSPATH') || exit;

add_action('rest_api_init', function (): void {

    register_rest_route('zme/v1', '/uploads', [
        [
            'methods' => 'POST',
            'callback' => 'zme_create_upload',
            'permission_callback' => 'zme_upload_permission',
        ],
        [
            'methods' => 'GET',
            'callback' => 'zme_list_uploads',
            'permission_callback' => 'zme_upload_permission',
        ],
    ]);

    register_rest_route('zme/v1', '/uploads/(?P<id>[a-f0-9-]{36})', [
        'methods' => 'GET',
        'callback' => 'zme_get_upload',
        'permission_callback' => 'zme_upload_permission',
    ]);

    register_rest_route(
        'zme/v1',
        '/uploads/(?P<id>[a-f0-9-]{36})/complete',
        [
            'methods' => 'POST',
            'callback' => 'zme_complete_upload',
            'permission_callback' => 'zme_upload_permission',
        ]
    );
});

function zme_upload_permission(
    WP_REST_Request $request
): bool {
    return is_user_logged_in()
        && current_user_can('upload_files')
        && wp_verify_nonce(
            (string) $request->get_header('X-WP-Nonce'),
            'wp_rest'
        );
}

هذا المسار مناسب لطلبات REST المعتمدة على جلسة WordPress وملفات تعريف الارتباط. أما خادم tus المستقل، فيحتاج إلى آلية مصادقة وتفويض خاصة به، مع ربط كل معرف رفع بمستخدمه والتحقق من ذلك عند كل طلب.

إنشاء جلسة رفع


<?php
function zme_create_upload(
    WP_REST_Request $request
): WP_REST_Response|WP_Error {
    global $wpdb;

    $name = sanitize_file_name(
        (string) $request->get_param('file_name')
    );
    $size = absint($request->get_param('file_size'));
    $mime = sanitize_mime_type(
        (string) $request->get_param('mime_type')
    );

    $max_size = 5 * 1024 * 1024 * 1024;

    if ($name === '' || $size < 1 || $size > $max_size) {
        return new WP_Error(
            'zme_invalid_file',
            'Invalid file name or size.',
            ['status' => 400]
        );
    }

    $allowed_mimes = get_allowed_mime_types();
    $type = wp_check_filetype($name, $allowed_mimes);

    if (empty($type['type']) || $mime !== $type['type']) {
        return new WP_Error(
            'zme_invalid_mime',
            'File type is not permitted.',
            ['status' => 415]
        );
    }

    $uuid = wp_generate_uuid4();
    $now = current_time('mysql', true);
    $expires = gmdate('Y-m-d H:i:s', time() + DAY_IN_SECONDS);

    $table = $wpdb->prefix . 'zme_upload_sessions';

    $inserted = $wpdb->insert(
        $table,
        [
            'upload_uuid' => $uuid,
            'user_id' => get_current_user_id(),
            'file_name' => $name,
            'file_size' => $size,
            'mime_type' => $type['type'],
            'status' => 'pending',
            'expires_at' => $expires,
            'created_at' => $now,
            'updated_at' => $now,
        ],
        ['%s', '%d', '%s', '%d', '%s', '%s', '%s', '%s', '%s']
    );

    if (!$inserted) {
        return new WP_Error(
            'zme_database_error',
            'Could not create upload session.',
            ['status' => 500]
        );
    }

    return new WP_REST_Response([
        'upload_id' => $uuid,
        'status' => 'pending',
        'expires_at' => $expires,
    ], 201);
}

هذا ينشئ سجل الجلسة فقط. لا يبدأ رفع البيانات قبل أن تنشأ جلسة tus الفعلية، ويتم التحقق من صلاحيتها وربطها بالسجل. كما أن فحص الامتداد وMIME في مرحلة إنشاء الجلسة فحص أولي، وليس بديلًا عن التحقق من محتوى الملف النهائي.

5. استرجاع الجلسة واستئناف الرفع

يجب أن يتمكن المستخدم من معرفة موضع توقفه واسترجاع جلسة الرفع حتى بعد مغادرة الصفحة.


<?php
function zme_get_upload(
    WP_REST_Request $request
): WP_REST_Response|WP_Error {
    global $wpdb;

    $uuid = sanitize_text_field($request['id']);
    $table = $wpdb->prefix . 'zme_upload_sessions';

    $session = $wpdb->get_row(
        $wpdb->prepare(
            "SELECT upload_uuid, file_name, file_size,
                    uploaded_bytes, status, expires_at
             FROM {$table}
             WHERE upload_uuid = %s AND user_id = %d",
            $uuid,
            get_current_user_id()
        ),
        ARRAY_A
    );

    if (!$session) {
        return new WP_Error(
            'zme_not_found',
            'Upload session not found.',
            ['status' => 404]
        );
    }

    $session['progress'] = $session['file_size'] > 0
        ? round(
            100 * $session['uploaded_bytes'] / $session['file_size'],
            2
        )
        : 0;

    return rest_ensure_response($session);
}

لاستئناف عملية tus، يرسل العميل طلب HEAD إلى رابط جلسة الرفع المخصص، ويقرأ ترويسة Upload-Offset التي يؤكدها الخادم. ثم يبدأ إرسال البيانات من هذا الموضع. يجب ألا يعتمد العميل على uploaded_bytes من قاعدة البيانات باعتباره المصدر الوحيد للحقيقة؛ فخادم tus هو المرجع الفعلي لموضع الرفع.

مخطط دورة استئناف الجلسة

6. كيف نرفع من الهاتف بعد مغادرة الصفحة؟

هذه النقطة هي من أهم الأجزاء في المشروع، لأنها تتطلب الفصل بين حفظ بيانات الجلسة واستمرار نقل البيانات.

موقع WordPress المتجاوب

يدعم اختيار الصور والفيديوهات من الهاتف، ويحفظ معرّف الجلسة وحالة العملية. عند العودة، يحاول استعادة الجلسة، وقد يطلب من المستخدم إعادة اختيار الملف إذا فقد المتصفح الوصول إليه.

IndexedDB

تخزن بيانات الجلسات وبيانات الاستئناف محليًا، مع الانتباه إلى أن تخزين ملف كامل بحجم عدة جيجابايت قد لا يكون ممكنًا أو ملائمًا على جميع الهواتف.

PWA وService Worker

تساعد على تحسين تجربة التطبيق وإدارة بعض الأعمال أثناء عمل التطبيق في الخلفية، لكنها لا تضمن استمرار رفع ملف كبير في كل المتصفحات، خصوصًا عند إغلاق التطبيق أو إيقافه بواسطة نظام التشغيل.

تطبيق Android أصلي

إذا كان المطلوب استمرار الرفع حتى عند مغادرة التطبيق، يمكن تطوير تطبيق Android يستخدم WorkManager أو آلية نقل خلفية ملائمة، مع مراعاة قيود البطارية والشبكة وسياسات النظام.

لذلك، إذا كان شرط العمل هو أن يبدأ المستخدم رفع فيديو ثم يغلق التطبيق بالكامل ويستمر الهاتف في رفعه دون تدخل، فالتصميم الأقوى هو تطبيق Android أصلي متصل بخادم tus، مع تطبيق ويب متكامل لمن يرغب في الرفع من المتصفح.

7. نظام المعالجة الخلفية Queue & Workers

بعد اكتمال رفع الملف، لا ينبغي أن يبقى المستخدم منتظرًا حتى تنتهي كل المعالجة. ننقل الملف إلى قائمة مهام خلفية، ونحدّث حالته عند كل مرحلة.

يمكن استخدام Action Scheduler لإدارة المهام في WordPress، أو استخدام طابور خارجي مثل Redis مع عمال PHP مستقلين عند ارتفاع الحمل.

مثال لدالة جدولة المعالجة:


<?php
/**
 * Schedule a processing job only once per upload.
 */
function zme_schedule_processing(string $uuid): bool {
    if (!wp_next_scheduled('zme_process_upload', [$uuid])) {
        return (bool) wp_schedule_single_event(
            time() + 1,
            'zme_process_upload',
            [$uuid]
        );
    }

    return true;
}

add_action('zme_process_upload', 'zme_process_upload_job');

function zme_process_upload_job(string $uuid): void {
    global $wpdb;

    $table = $wpdb->prefix . 'zme_upload_sessions';

    // Atomically claim a session for processing.
    $claimed = $wpdb->query(
        $wpdb->prepare(
            "UPDATE {$table}
             SET status = 'processing',
                 updated_at = %s
             WHERE upload_uuid = %s
               AND status = 'uploading'
               AND uploaded_bytes = file_size",
            current_time('mysql', true),
            $uuid
        )
    );

    if ($claimed !== 1) {
        return;
    }

    // Next: verify tus completion, validate the file,
    // move it to final storage and register its media record.
    // Each step must be idempotent and recoverable.
}

هذه نواة جدولة وحجز للمعالجة، وليست عاملًا مكتملًا لتجميع الملف. يلزم ربطها بحدث إتمام موثوق من خادم tus، وإضافة آلية إعادة المحاولة واستعادة المهام العالقة. كما أن WP-Cron قد لا يعمل في موعد دقيق على المواقع قليلة الزيارات؛ لذلك يفضل استخدام Cron حقيقي أو عامل دائم في بيئة الإنتاج.

8. مستويات الأداء والتوسع

يعتمد الأداء الفعلي على سرعة اتصال المستخدم، وموقع الخادم، وسرعة القرص أو التخزين السحابي، وعدد الاتصالات المتزامنة.

إعدادات مبدئية قابلة للتعديل

الإعدادالقيمة التجريبية
حجم الجزء8 MB
عدد الاتصالات المتزامنة لكل عميل3
الحد الأقصى التجريبي للملف5 GB
عدد محاولات إعادة الإرسال5
انتهاء الجلسة غير النشطة24 ساعة
تخزين الأجزاءخارج مجلد الويب
معالجة الفيديوعامل خلفي

حاسبة تقديرية لمدة الرفع

جرّب حجم الملف وسرعة الاتصال لمعرفة الزمن النظري التقريبي.حجم الملف

2.0 GB

100 MB

10 GBسرعة الرفع

10 Mbps

1 Mbps

100 Mbpsهامش إضافي للتأخير

15%

الوقت التقديري النظري

2 دقيقة

الحساب يفترض سرعة ثابتة بالـMbps، مع هامش إضافي. الانقطاعات أو قيود الشبكة والخادم قد تزيد الوقت.

9. تحويل المشروع إلى خدمة SaaS متعددة العملاء

بما أن المنصة قابلة للتطوير كمنتج مستقل، يمكن تصميمها منذ البداية لدعم مؤسسات متعددة، بحيث يمتلك كل عميل مساحة تخزين وصلاحيات وحدود استخدام مستقلة.

الميزةStarterBusinessEnterprise
رفع الملفاتمحدودموسعقابل للتخصيص
استكمال الرفعنعمنعمنعم
تخزين سحابياختياريمتاحمتعدد المواقع
إدارة المستخدمينفرديفريقأدوار متقدمة
واجهة APIأساسيةمتقدمةمخصصة
سجلات التدقيقأساسيةموسعةمتقدمة
العلامة البيضاءلااختياريةنعم

هذه باقات مقترحة لتصميم المنتج، وليست عروضًا تجارية أو حدود استخدام تم تفعيلها.

يجب أن تحتوي كل جلسة رفع على tenant_id، مع التحقق منه في كل طلب، حتى لا يستطيع عميل الوصول إلى ملفات أو سجلات عميل آخر. كما يجب حساب استهلاك التخزين وحركة البيانات على مستوى كل مؤسسة.

10. خطة اختبار الجودة قبل الإطلاق

قائمة اختبار الإصدار

0 / 10 مكتمل

رفع صورة صغيرة من Android وiPhone

رفع فيديو كبير من اتصال بطيء

قطع الإنترنت أثناء رفع الملف واستعادته

تحديث الصفحة واستعادة جلسة رفع

إغلاق المتصفح والتحقق من الاستئناف بعد العودة

منع المستخدم من الوصول إلى جلسة مستخدم آخر

اختبار الملفات ذات الامتدادات أو المحتويات المزيفة

اختبار فشل التخزين أو امتلاء مساحة الخادم

اختبار عشرات عمليات الرفع المتزامنة

التحقق من تسجيل الملف النهائي في مكتبة WordPressإعادة تعيين

قائمة تفاعلية لمتابعة الاختبارات يدويًا، ولا تمثل نتائج اختبارات فعلية.

11. التوصية التقنية النهائية

البنية الموصى بها لـ Zezo Media Engine

  • WordPress + PHP 8.2 أو أحدث: إدارة المستخدمين، الصلاحيات، البيانات والوسائط.
  • Uppy + tus: واجهة الرفع ومحرك الاستئناف.
  • tusd: استقبال البيانات وإدارة مواضع الرفع.
  • MySQL: حفظ بيانات الجلسات وسجل العمليات.
  • Redis أو Action Scheduler: تنظيم مهام المعالجة وإعادة المحاولة وفق حجم المشروع.
  • S3-compatible Storage: تخزين الملفات النهائية على بنية مستقلة قابلة للتوسع.
  • PWA أو Android Native: تحسين تجربة الرفع في الخلفية وفق مستوى الاستمرارية المطلوب.

بهذه البنية يصبح المشروع أكثر من مجرد أداة رفع ملفات؛ إنه محرك وسائط قابل للتكامل مع متجر WooCommerce، ومواقع WordPress متعددة، ومنصة SaaS مستقلة.

الخطوة البرمجية التالية: تنفيذ حزمة الإضافة كاملة، وربط REST API بخادم tus فعلي، وإضافة واجهة لوحة التحكم وملفات JavaScript وCSS، ثم بناء نسخة ZIP واختبارها على بيئة WordPress تجريبية. حتى ذلك الحين، تظل الأكواد والهياكل الواردة هنا أساسًا هندسيًا أوليًا وليست إصدارًا مثبتًا أو مختبرًا في الإنتاج.

Scroll to Top

🤖 موصى به لك بناءً على اهتماماتك