ثبت ویجت‌های سفارشی در داشبورد اصلی CRM

نحوه ثبت ویجت‌های سفارشی که در داشبورد اصلی CRM نمایش داده می‌شوند.


مرور کلی

فیلتر `la24_widgets` ویجت‌های سفارشی را برای داشبورد اصلی CRM ثبت می‌کند. ادمین می‌تواند ویجت‌ها را از طریق رابط داشبورد (یک گرید مبتنی بر Gridster) اضافه، حذف و مرتب‌سازی کند. هر کلاس ویجت **باید** از کلاس انتزاعی `\LoyalAxis\classes\services\widgets\Widget` که در `includes/classes/services/widgets/Widget.php` تعریف شده ارث‌بری کند — LA24Core کلاس شما را به‌صورت `new $callback( $widget_id, $params )` نمونه‌سازی کرده و متدهای چرخه حیات آن را مستقیماً فرا می‌خواند، بنابراین یک کلاس ساده که از این کلاس پایه ارث‌بری نکند با خطای Fatal مواجه می‌شود.

امضای هوک

php
apply_filters( 'la24_widgets', array $widgets );
**نوع:** Filter **پارامترها:** `$widgets` (آرایه) — رجیستری ویجت‌های فعلی **بازگشتی:** آرایه — رجیستری ویجت‌های تغییریافته
> **نکته:** برای خواندن رجیستری، مستقیماً `apply_filters( 'la24_widgets', ... )` را فراخوانی نکنید. به‌جای آن از `la24_get_widget_items()` (‏`includes/helpers/la24-core-functions.php`) استفاده کنید — این تابع هم فیلتر را اعمال می‌کند و هم هر ویجت را نرمالایز می‌کند (آیکون پیش‌فرض و fallback دسته‌بندی که در ادامه توضیح داده شده را اختصاص می‌دهد) پیش از بازگرداندن آرایه. این همان چیزی است که هم کنترلرهای داشبورد و هم مودال «افزودن ویجت» از آن استفاده می‌کنند.

ثبت یک ویجت

php
add_filter( 'la24_widgets', function ( $widgets ) {

    $widgets['900'] = array(
        'name'       => __( 'خلاصه CRM من', 'my-crm-ext' ),
        'class_icon' => 'fa fa-pie-chart',
        'category'   => array( 'reporting' ),
        'callback'   => '\MyPlugin\Widgets\CrmSummaryWidget',
    );

    return $widgets;
} );

فیلدهای ویجت

فیلدنوعتوضیح
کلید (کلید آرایه)stringشناسه عددی منحصربه‌فرد ویجت (قراردادهای شناسه را ببینید)
`name`stringنام نمایشی ویجت در انتخابگر ویجت داشبورد
`class_icon`string*اختیاری.* کلاس FontAwesome برای آیکون ویجت. در صورت عدم تعیین، `la24_get_widget_items()` یک آیکون پیش‌فرض (`fas fa-th-large`) اختصاص می‌دهد.
`category`string\array
`callback`stringنام کامل کلاس ویجت (با namespace)؛ باید از `Widget` ارث‌بری کند

دسته‌بندی‌های ویجت

ویجت‌ها می‌توانند یک یا چند برچسب دسته‌بندی تعریف کنند تا در مودال «افزودن ویجت به داشبورد» قابل جست‌وجو و فیلتر باشند. دسته‌بندی‌ها توسط `la24_get_widget_items()` — همان تابعی که تمام کنترلرها و تمپلیت مودال برای خواندن رجیستری استفاده می‌کنند — نرمالایز (و در صورت نیاز پیش‌فرض‌گذاری) می‌شوند، بنابراین شما هرگز نیازی به مدیریت دستی fallback ندارید.
php
function la24_get_widget_categories(); // includes/helpers/la24-core-functions.php
این تابع طبقه‌بندی ثابت مورد استفاده در سراسر LA24Core را برمی‌گرداند:
Slugبرچسبآیکون
`administrative`ویجت‌های مدیریتی`fas fa-user-shield`
`woocommerce_panel`پنل کاربری ووکامرس`fas fa-shopping-cart`
`operational`عملیاتی`fas fa-cogs`
`reporting`گزارش‌گیری`fas fa-chart-line`
`general`عمومی`fas fa-th-large`
یک یا چند برچسب را روی ویجت خود تعریف کنید:
php
$widgets['900'] = array(
    'name'       => __( 'خلاصه CRM من', 'my-crm-ext' ),
    'class_icon' => 'fa fa-pie-chart',
    'category'   => array( 'reporting' ),
    'callback'   => '\MyPlugin\Widgets\CrmSummaryWidget',
);
  • هر برچسبی که ارائه دهید و در فهرست بالا نباشد، به‌طور خاموش نادیده گرفته می‌شود.
  • اگر `category` تعیین نشود یا هیچ‌کدام از برچسب‌های ارائه‌شده شناخته‌شده نباشند، ویجت به‌طور پیش‌فرض در دسته `general` قرار می‌گیرد.
  • این طبقه‌بندی ثابت است — هیچ فیلتری برای افزودن دسته‌بندی سفارشی وجود ندارد. اگر افزونه شما در هیچ‌کدام از این برچسب‌ها جا نمی‌شود، `general` انتخاب مناسبی است.

قراردادهای شناسه ویجت

کلیدهای آرایه ویجت، رشته‌های عددی هستند. ماژول‌های داخلی خود LA24Core، شناسه‌هایی از `100` تا نزدیک `800` را اشغال کرده‌اند (مثلاً `100` برای ویجت داخلی دکمه لینک، `101` تا `110` برای UMS/Office/Voip، `200` تا `206` برای گزارش‌ها، `301` تا `306` برای پنل کاربری ووکامرس، `401`/`402` برای اعلان‌ها، `600` تا `604` برای گزارش‌های ووکامرس، `702` برای تحلیل شکست فرصت فروش).
  • **ویجت‌های افزونه‌های سفارشی و شخص‌ثالث باید از شناسه عددی `900` یا بالاتر استفاده کنند** (مثلاً `'900'`، `'901'`، `'9001'`) تا هرگز با شناسه‌ای که در نسخه‌های آینده LA24Core به هسته اضافه می‌شود تداخل نداشته باشند.
  • کلید را با یک رشته پیشوندی نسازید (`'my_plugin_201'`) — کلید باید همان شناسه عددی خالص باشد، زیرا دقیقاً به همین شکل در داده‌های سریالایز‌شده چیدمان داشبورد ذخیره شده و از طریق `la24_get_widget_items()[$id]` جست‌وجو می‌شود.
php
// درست
$widgets['900'] = array( ... );
$widgets['901'] = array( ... );

// از این اجتناب کنید — پایین‌تر از بازه رزرو شده برای افزونه‌های سفارشی، ممکن است با یک ویجت هسته تداخل داشته باشد
$widgets['201'] = array( ... );

// از این اجتناب کنید — کلید باید عددی باشد، نه یک رشته با پیشوند
$widgets['my_deals_900'] = array( ... );

کلاس پایه Widget

فایل `includes/classes/services/widgets/Widget.php` قراردادی را تعریف می‌کند که هر کلاس ویجت باید رعایت کند. یک کلاس ویجت واقعی باید تمام اعضای انتزاعی زیر را پیاده‌سازی کند:
عضوامضاهدف
`content()``public function content( $settings )`خروجی HTML ویجت را echo می‌کند
`desktop_size()``public static function desktop_size()`مقادیر `size_x`/`size_y`/`minx`/`miny`/`maxx`/`maxy` را برای گرید دسکتاپ برمی‌گرداند
`mobile_size()``public static function mobile_size()`مشابه بالا، برای گرید موبایل
`default_settings()``public function default_settings(): array`آرایه تنظیمات پیش‌فرض را برمی‌گرداند (کلیدهایی که ذخیره می‌شوند را نیز مشخص می‌کند)
`widget_title()``public function widget_title()`عنوانی که در هدر/تمپلیت ویجت نمایش داده می‌شود را برمی‌گرداند
`widget_bg_color()``public function widget_bg_color()`رنگ پس‌زمینه‌ای که تمپلیت مشترک ویجت استفاده می‌کند را برمی‌گرداند
`style_settings()``public function style_settings( $settings )`تب «Style» فرم تنظیمات ویجت را echo می‌کند
`master_settings()``public function master_settings( $settings )`تب «مدیریت» فرم تنظیمات ویجت را echo می‌کند
کلاس پایه از قبل موارد زیر را مدیریت می‌کند: سازنده (`$widget_id`، `uniq_id`، `tab`، `type`، `device`، `user_id`)، بارگذاری/ادغام تنظیمات ذخیره‌شده از طریق `get_settings()`، ذخیره تنظیمات از طریق `save_Settings()`، بررسی دسترسی‌ها (`la24_view_widget_{id}`، `la24_setting_admin_widget_{id}`)، و رندر پوسته مشترک ویجت (`template()`) مگر اینکه `use_template()` را override کرده و `false` برگردانید.

نوشتن یک کلاس ویجت

از ویجت داخلی `Simple_Button` (`includes/classes/services/widgets/Simple_Button.php`، ثبت‌شده با شناسه هسته‌ای `100`) به‌عنوان پیاده‌سازی مرجع استفاده کنید:
php
<?php

namespace MyPlugin\Widgets;

defined( 'ABSPATH' ) || exit;

use LoyalAxis\classes\services\widgets\Widget;
use LoyalAxis\classes\utilities\Form;

class CrmSummaryWidget extends Widget {

    public function content( $settings ) {
        global $wpdb;

        $total = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}my_crm_records" );

        echo "<div class='small-box' style='box-shadow: none !important;'>
                <div class='inner'>
                    <h3 style='color: {$settings['text_color_900']};'>
                        <span style=\"font-size: 20px;\">" . esc_html( $total ) . "</span>
                    </h3>
                    <p>" . esc_html__( 'تعداد کل رکوردها', 'my-crm-ext' ) . "</p>
                </div>
              </div>";
    }

    public static function desktop_size() {
        return array(
            'size_x' => 3, 'size_y' => 1,
            'minx'   => 1, 'miny'   => 1,
            'maxx'   => 6, 'maxy'   => 12,
        );
    }

    public static function mobile_size() {
        return array(
            'size_x' => 2, 'size_y' => 1,
            'minx'   => 1, 'miny'   => 1,
            'maxx'   => 2, 'maxy'   => 6,
        );
    }

    public function default_settings(): array {
        return array(
            'head_text_900'  => __( 'خلاصه CRM', 'my-crm-ext' ),
            'text_color_900' => 'rgba(0,0,0,1)',
        );
    }

    public function widget_title() {
        return $this->settings['head_text_900'] ?? '';
    }

    public function widget_bg_color() {
        return 'rgba(255,255,255,1)';
    }

    public function style_settings( $settings ) {
        echo Form::start_form( 0, 'la24-section-box' );
        echo Form::header( __( 'تنظیمات ظاهری:', 'my-crm-ext' ), 12, 'la24-titr' );
        echo Form::color_picker( __( 'رنگ متن', 'my-crm-ext' ), 6, 'text_color_900', 'text_color_900', 'center', $settings['text_color_900'], 0, '' );
        echo Form::close_form();
    }

    public function master_settings( $settings ) {
        echo Form::start_form( 0, 'la24-section-box' );
        echo Form::header( __( 'تنظیمات مدیریتی:', 'my-crm-ext' ), 12, 'la24-titr' );
        echo Form::text_input( __( 'عنوان', 'my-crm-ext' ), 6, 'head_text_900', 'head_text_900', '', $settings['head_text_900'], '', 0 );
        echo Form::close_form();
    }
}
آن را با شناسه‌ای `900` یا بالاتر ثبت کنید، همان‌طور که در بخش [ثبت یک ویجت](#ثبت-یک-ویجت) نشان داده شد.

فرم‌های تنظیمات

هر دو متد `style_settings()` و `master_settings()` آرایه `$settings` فعلی ویجت را دریافت کرده و انتظار می‌رود فرمی ساخته‌شده با کمک‌کننده `\LoyalAxis\classes\utilities\Form` (`includes/classes/utilities/Form.php`) را `echo` کنند — همان کمک‌کننده‌ای که در سراسر صفحات مدیریت LA24Core استفاده می‌شود. بلوک‌های رایج: `Form::start_form()`، `Form::header()`، `Form::text_input()`، `Form::checkbox()`، `Form::color_picker()`، `Form::close_form()`. نام/شناسه فیلدهایی که به این کمک‌کننده‌ها می‌دهید باید با کلیدهای بازگردانده‌شده از `default_settings()` مطابقت داشته باشد، زیرا `Widget::save_Settings()` مقادیر ارسالی را با پیمایش همان کلیدها می‌خواند.

Query های پایگاه‌داده در ویجت‌ها

ویجت‌ها در هر بارگذاری صفحه داشبورد اجرا می‌شوند، پس query های داخل `content()` را بهینه نگه دارید:
php
public function content( $settings ) {
    global $wpdb;

    // از get_var برای مقادیر تکی استفاده کنید
    $total = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}my_table" );

    // از get_results برای آمار گروه‌بندی‌شده استفاده کنید
    $stats = $wpdb->get_results(
        "SELECT status, COUNT(*) as total FROM {$wpdb->prefix}my_table GROUP BY status"
    );
}
از JOIN های سنگین یا full-table scan در `content()` خودداری کنید. در صورت نیاز از WordPress transient ها برای cache کردن نتایج استفاده کنید.