mehdi keyvani 02 دی 1395 بدون نظر 283 بازدید آموزش طراحی سایت
ایجاد لایسنس قالب وردپرس Licensed Controlled Theme | بخش اول

ایجاد لایسنس قالب وردپرس Licensed Controlled Theme و پلاگین بروزرسانی سیستم، بخش اول:

پلاگین License Manager
به همان اندازه که قالب رسمی وردپرس و دایرکتوری‌های پلاگین خوب هستند، مواقعی وجود دارد که شما نمیخواهید از آنها برای توزیع قالب یا پلاگینتان استفاده کنید. شاید به این دلیل است آنها را به فروش می‌گذارید، یا شاید می‌خواهید آنها را برای خودتان نگه ‌دارید، و دردسترس سازمان یا گروهی از دوستانتان قرار دهید.

اما در مورد بروزرسانی چطور؟

اگر فقط حساب کاربری خودتان را دارید، کافیست پلاگین یا قالب را به صورت دستی آپلود کنید. ولی اگر بیش از یک کاربر دارید، از بخش بروزرسانی پیشخوان مدیر به سادگی استفاده کنید.

عملکرد بروزرسانی وردپرس، اصولا فقط برای قالب‌ها و پلاگین‌های رسمی وردپرس طراحی شده است، اما نگران نباشید: وردپرس عملیات و فیلترهایی دارد که با اجرای آنها، نفوذ به این عملکرد را برا ما ممکن می‌سازد و می‌توانیم سرور خودمان را به آن ترکیب اضافه کنیم.

شما چه چیزی یاد می‌گیرید

در اولین آموزش این دوره، ساخت یک پلاگین وردپرس برای تبدیل وب‌سایت به سرور مدیریت لایسنس را شروع می‌کنیم. در بخش دوم، ساخت پلاگین با افزودن یک API به آن ادامه می‌دهیم. در بخش سه، از همان API برای ایجاد لایسنس قالب وردپرس یا پلاگین وردپرس استفاده می‌کنیم، تا برای بروزرسانی به مدیر لایسنس جواب برگشتی بدهد.

• در طول ساخت پلاگین، در بخش اول، موارد زیر را در مورد فناوری‌های توسعه پلاگین وردپرس یاد خواهید گرفت:
• استفاده یک قالب استاندارد پلاگین وردپرس برای شروع فوری.
• ایجاد یک نوع پست سفارشی جدید با یک متا باکس برای ذخیره سفارشی فراداده‌ها.
• ایجاد یک جدول پایگاه‌داده قابل نگهداری برای پلاگینتان.
• افزودن عناصر به جدول پایگاه‌داده.
• مرتب‌سازی عناصر با استفاده از پیاده سازی جدول شخصی وردپرس.
اگر می‌خواهید پلاگین را عملا ببینید، می‌توانید رایجترین نسخه‌های پلاگین را از سایت wordpress.org دانلود کنید. ما قدم به قدم ساخت پلاگین را دنبال می‌کنیم، اما اگر نمی‌خواهید همه چیز را از اول بسازید، کافیست با کدهای منبعی که در این آموزش قرار داده شده همراه شوید.

حالا شروع به کار کنید.

۱- ایجاد پلاگین با استفاده از قالب استاندارد پلاگین وردپرس
شروع به کار با یک پلاگین وردپرس جدید شامل کارهای تکراری زیادی نظیر نوشتن کدجدید، نسخه برداری و پاکسازی پروژه‌های قدیمی است، که برای ایجاد هر پلاگینی انجام می‌شود.

اما یک راه بهتر هست.

این بار، به جای نسخه‌برداری از یک پروژه یا شروع از چک نویس، از قالب استاندارد پلاگین وردپرس تام مک‌فارلین استفاده می‌کنیم، این طراحی کمک می‌کند که شما با پلاگین وردپرس شیء‌گرا و ساخت یافته شروع به کار کنید.
پس، قبل از شخصی‌سازی، پلاگین اصلی را با استفاده از قالب استاندارد پلاگین مقدمه‌چینی کنید.

دانلود قالب استاندارد و شخصی‌سازی آن
برای دانلود آسان آخرین نسخه قالب استاندارد پلاگین به صورت فشرده کافیست به سایت آن مراجعه کنید.

پس از دانلود آنرا از حالت فشرده خارج کنید، سپس پوشه trunk را پیدا کرده، در پایان در محل موردنظر کپی کرده و نام آنرا به wp-license-manager تغییر دهید.

سپس، وقت آن است که از طریق فایل‌های قالب استاندارد پلاگین آنها را شخصی‌سازی کنیم:

۱- از طریق فایل‌های موجود در پوشه‌ها و زیرپوشه‌ها نام رویدادهای plugin-name را به wp-license-manager و Plugin_Name را به Wp_License_Manager تغییر دهید. مطمئن شوید که هم نام کلاس‌ها و هم نام فایل‌هایشان تغییر کرده است. کمی زمانتان را خواهد گرفت، پس راه بهتر برای تغییر نام استفاده از PHP IDE است.
۲- اطلاعات پلاگین را به فایل بوت‌استرپ پلاگین اضافه کرده، و نام آنرا به wp-license-manager.php تغییر دهید سپس در پوشه روت پلاگین قرار دهید. اطلاعات را در بخش توضیح در بالای فایل، بعد از تگ wordpress-plugin که مربوط به PHP Doc است، خواهید دید.

حالا شما یک پلاگین خالی با پیکربندی اصولی ساختید، که منتظر افزودن عملکرد است. زمان آن رسیده که مدیریت لایسنس خود را بسازید.
اگر می‌خواهید در مورد قالب استاندارد بیشتر بدانید، مجموعه آموزشی تام مک‌فارلین را بررسی کنید.

۲- ایجاد یک نوع پست سفارشی برای محصولات

پلاگین مدیریت لایسنس ما کاملا ساده است و دو نوع داده‌ای که ذخیره و استفاده می‌کند، محصولات و لایسنس‌ها هستند. که محصولات پیش‌نیازی برای ساخت لایسنس‌ها هستند( و بین این دو محصولات ساده‌ترین هستند ).

این تصویر نشان‌دهنده چیزی‌ است که شما در این بخش درست می‌کنید.

پلاگین مدیریت لایسنس, ایجاد لایسنس قالب وردپرس, ساخت لایسنس وردپرس, کد لایسنس برای قالب

محصول، نشان‌دهنده یک قالب یا پلاگین وردپرس است، که می‌خواهید از طریق سرور مدیریت لایسنس آنرا مدیریت کنید. مانند پست یا صفحه وبلاگ، یک محصول نام و توضیح دارد. علاوه بر این دارای چند فیلد اضافی برای تعریف اطلاعات خاص محصول است:
نسخه: شماره نسخه محصول است که این فیلد برای بررسی بروزرسانی استفاده می‌شود و در قسمت دوم و سوم این مجموعه آموزشی بیان شده است.
باکت فایل: باکت فایل اس۳ آمازون در این فیلد ذخیره می‌شود.
نام فایل: نام فایل محصولی که به صورت فشرده‌شده در اس۳ آمازون ذخیره شده، است. در ارتباط با گزینه‌‌های مربوط به فایل در قسمت دوم صحبت خواهد شد.
آزمایش با نسخه وردپرس، نسخه موردنیاز وردپرس، آخرین آپدیت، بنر بالایی و بنر پایینی: این گزینه‌ها هم در بخش بروزرسانی رابط کاربری پلاگین در قسمت سوم بیان خواهد شد.
حالا، شروع به ساخت نوع پست سفارشی کرده و به آن یک متاباکس اضافه می‌کنیم.

قدم اول: ایجاد نوع پست
به طور منطقی، قالب استاندارد پلاگین عملکرد پلاگین را به دو قسمت تقسیم کرده است: عملکرد ظاهری عمومی و عملکرد مدیر. حال آنکه این قسمت‌بندی در بیشتر موارد مفهوم پیدا کرده است، انواع پست هم دراین بین هستند، و شما می‌توانید در هر دو قسمت آنها را قرار دهید. من عمومی را پیشنهاد می‌کنم.
پس، به دنبال تابع define_public_hooks در کلاس Wp_License_Manager در فایل includes/class-wp-license-manager.php بگردید، و خط جدید زیر را درست بعد از دو عمل wp_enqueue_script اضافه کنید.

1- $this->loader->add_action( 'init', $plugin_public, 'add_products_post_type' );

این خط، از عملکرد قالب استاندارد و بارکننده فیلتر برای افزودن یک کنترل‌کننده عمل به عمل init وردپرس استفاده می‌کند.تابع، add_products_post_type را در کلاس Wp_License_Manager_Public مشاهده می‌شود.

در اینجا همه تابع را مشاهده می‌کنید:

/**
 * Register the new "products" post type to use for products that
 * are available for purchase through the license manager.
 */
public function add_products_post_type() {
    register_post_type( 'wplm_product',
        array(
            'labels' => array(
                'name' => __( 'Products', $this->plugin_name ),
                'singular_name' => __( 'Product', $this->plugin_name ),
                'menu_name' => __( 'Products', $this->plugin_name ),
                'name_admin_bar' => __( 'Products', $this->plugin_name ),
                'add_new' => __( 'Add New', $this->plugin_name ),
                'add_new_item' => __( 'Add New Product', $this->plugin_name ),
                'edit_item' => __( 'Edit Product', $this->plugin_name ),
                'new_item' => __( 'New Product', $this->plugin_name ),
                'view_item' => __( 'View Product', $this->plugin_name ),
                'search_item' => __( 'Search Products', $this->plugin_name ),
                'not_found' => __( 'No products found', $this->plugin_name ),
                'not_found_in_trash' => __( 'No products found in trash', $this->plugin_name ),
                'all_items' => __( 'All Products', $this->plugin_name ),
            ),
            'public' => true,
            'has_archive' => true,
            'supports' => array( 'title', 'editor', 'author', 'revisions', 'thumbnail' ),
            'rewrite' => array( 'slug' => 'products' ),
            'menu_icon' => 'dashicons-products',
        )
    );
}

بیایید ببینیم این تابع چه کاری انجام می‌دهد، یا به عبارت دیگر، پارامترها چه کاری با تابع register_post_type وردپرس انجام می‌دهند.

پارامتر اول، $post_type، ( خط شش ) شناسه‌ی نوع پست که در پیوندهای مدیر وردپرس استفاده شده را تعریف کرده و پست‌های این نوع را جستجو می‌کند( من از wplm_product استفاده کردم، برای جلوگیری از تداخل با انواع پست ایجاد شده در دیگر پلاگین‌ها و قالب‌ها).

پارامتر دوم( خط ۷ تا ۲۸ ) آرایه‌ای برای تعریف خواص نوع پست است( برای مشاهده لیست کامل گزینه‌ها، وردپرس کدکس را بررسی کنید):

Labels: تعیین مجموعه‌ای از برچسب‌های رشته‌ای ، که به نوع پست در محدوده مدیر وردپرس اشاره دارد.
Public: ظاهر پست‌های نوع جدید را مشخص می‌کند. چون می‌خواستم محصولات، قابل جستجو توسط بازدید کنندگان باشند پس مقدار این مجموعه را true کردم.
Has_archive: مشخص می‌کند که آیا وردپرس از یک صفحه‌ی آرشیو برای لیست کردن پست‌ها استفاده می‌کند یا نه؟
Supports: مشخص می‌کند، که کدام مشخصه‌های ویرایش پست در ویرایشگر پست نمایش داده شود.
Rewrite: چگونگی نمایش لینک‌های دائمی را برای نوع محصول مشخص می‌کند.
Menu_icon: آیکونی برای نوع پست در منوی مدیر مشخص می‌کند. سایت WordPress Developer را برای مشاهده آیکون‌های بیشتر بررسی کنید.
اکنون لیست کردن، افزودن، و ویرایش محصولات همگی تحت کنترل وردپرس است. حال باید متاباکس زیر را با لیستی از تنظیمات سفارشی اضافه کنیم.

قدم دوم: افزودن متاباکس برای اطلاعات محصول

اکنون نوع محصول سفارشی برای محصولات را ساختیم، و همه چیز برای ذخیره محصولات در سیستم مدیریت لایسنس فراهم است. اما یک متاباکس برای اطلاعات محصول اضافه کنید، تا نوع پست مفیدتر شود.
متاباکس مانند تصویر زیر است:
ایجاد لایسنس قالب وردپرس, ساخت لایسنس وردپرس, کد لایسنس برای قالب
ابتدا یک ترفند برای افزودن متاباکس به کار ببرید. Add_meta_boxes_{post_type} گزینه مناسبی است: بسادگی نوع پست را به جای {post_type} قرار دهید و این ترفند زمانی فراخوانی می‌شود که بخواهید متاباکس‌هایی را برای همان پست اضافه کنید.( در اینجا wplm_product است).

چون ما در محدوده ادمین کار میکنیم، کد زیر را به تابع define_admin_hooks() در کلاس پلاگین اصلی Wp_License_Manager اضافه کنید:

$this>loader>add_action('add_meta_boxes_wplm_product',$plugin_admin,'add_product_information_meta_box' );

تابع، add_product_information_meta_box() در Wp_License_Manager_Admin ، به سادگی متاباکس و یک تابع ترجمه شده را برای نمایش محتوای آن، مشخص می‌کند:

/**
 * Registers a meta box for entering product information. The meta box is
 * shown in the post editor for the "product" post type.
 *
 * @param   $post   WP_Post The post object to apply the meta box to
 */
public function add_product_information_meta_box( $post ) {
    add_meta_box(
        'product-information-meta-box',
        __( 'Product Information', $this->plugin_name ),
        array( $this, 'render_product_information_meta_box' ),
        'wplm_product',
        'side'
    );
}

این تابع برای مشخص کردن یک متاباکس، تابع add_meta_box وردپرس را فراخوانی می‌کند. پارامترها به ترتیب عبارتنداز:
۱- id$: مقدار فیلد آی‌دی HTML برای عنصر متاباکس.
۲- title$: موضوع متاباکس که در بالا قرار دارد.
۳- callback$: تابعی که متاباکس را تفسیر می‌کند.
۴- post_type$: نوع پست که باید در صفحه ویرایشگر، روی متاباکس نمایش یابد.
۵- context$: موقعیتی که متاباکس باید قرار بگیرد( ‘نرمال’، ‘پیشرفته’ یا ‘یکسو’).

سپس، تابع تفسیرشده‌ای که در پارامتر سوم تعریف کردیم را اضافه می‌کنیم:

/**
 * Renders the product information meta box for the given post (wplm_product).
 *
 * @param $post     WP_Post     The WordPress post object being rendered.
 */
public function render_product_information_meta_box( $post ) {
    $product_meta = get_post_meta( $post->ID, 'wp_license_manager_product_meta', true );
 
    if ( ! is_array( $product_meta ) ) {
        $product_meta = array(
            'file_bucket' => '',
            'file_name' => '',
            'version' => '',
            'tested' => '',
            'requires' => '',
            'updated' => '',
            'banner_low' => '',
            'banner_high' => ''
        );
    }
 
    $this->render_nonce_field( 'product_meta_box' );
 
    require( 'partials/product_meta_box.php' );
}

خط ۷: این تابع با خوانده شدن در فراداده جدید، اجرا می‌شود.

خط ۹ تا ۲۰: اگر فراداده خالی باشد، یک آرایه فراداده با مقادیر خالی به طور پیشفرض ایجاد می‌کند.

خط ۲۲: با چاپ یک فیلد موقتی موارد امنیتی را هنگام ذخیره‌سازی داده حفظ می‌کند. render_nonce_field یک تابع کمکی است که برای یادآوری نام‌های موقت ساختم. بعدا آنرا اضافه خواهم کرد.

خط ۲۴: شامل متاباکس فعلی HTML است. پوشه partials بخشی از قالب استاندارد پلاگین وردپرس است که برای جدا کردن کد HTML از PHP استفاده می‌شود. در زیر قالبی که فایل متاباکس باید باشد مشاهده می‌کنید:

<?php
/**
 * The view for the plugin's product meta box. The product meta box is used for
 * entering additional product information (version, file bucket, file name).
 *
 * @package    Wp_License_Manager
 * @subpackage Wp_License_Manager/admin/partials
 */
?>
<p>
    <label for="wp_license_manager_product_version">
        <?php _e( 'Version:', $this->plugin_name ); ?>
    </label>
    <input type="text" id="wp_license_manager_product_version"
           name="wp_license_manager_product_version"
           value="<?php echo esc_attr( $product_meta['version'] ); ?>"
           size="25" >
</p>
<p>
    <label for="wp_license_manager_product_tested">
        <?php _e( 'Tested with WordPress version:', $this->plugin_name ); ?>
    </label>
    <input type="text" id="wp_license_manager_product_tested"
           name="wp_license_manager_product_tested"
           value="<?php echo esc_attr( $product_meta['tested'] ); ?>"
           size="25" >
</p>
<p>
    <label for="wp_license_manager_product_requires">
        <?php _e( 'Requires WordPress version:', $this->plugin_name ); ?>
    </label>
    <input type="text" id="wp_license_manager_product_requires"
           name="wp_license_manager_product_requires"
           value="<?php echo esc_attr( $product_meta['requires'] ); ?>"
           size="25" >
</p>
<p>
    <label for="wp_license_manager_product_updated">
        <?php _e( 'Last updated:', $this->plugin_name ); ?>
    </label>
    <input type="text" id="wp_license_manager_product_updated"
           name="wp_license_manager_product_updated"
           value="<?php echo esc_attr( $product_meta['updated'] ); ?>"
           size="25" >
</p>
 
<p>
    <label for="wp_license_manager_product_banner_low">
        <?php _e( 'Banner low:', $this->plugin_name ); ?>
    </label>
    <input type="text" id="wp_license_manager_product_banner_low"
           name="wp_license_manager_product_banner_low"
           value="<?php echo esc_attr( $product_meta['banner_low'] ); ?>"
           size="25" >
</p>
 
<p>
    <label for="wp_license_manager_product_banner_high">
        <?php _e( 'Banner high:', $this->plugin_name ); ?>
    </label>
    <input type="text" id="wp_license_manager_product_banner_high"
           name="wp_license_manager_product_banner_high"
           value="<?php echo esc_attr( $product_meta['banner_high'] ); ?>"
           size="25" >
</p>
 
<h3>Download</h3>
 
<p>
    <label for="wp_license_manager_product_bucket">
        <?php _e( 'Amazon S3 Bucket:', $this->plugin_name ); ?>
    </label>
    <input type="text" id="wp_license_manager_product_bucket"
           name="wp_license_manager_product_bucket"
           value="<?php echo esc_attr( $product_meta['file_bucket'] ); ?>"
           size="25" />
</p>
<p>
    <label for="wp_license_manager_product_file_name">
        <?php _e( 'Amazon S3 File Name:', $this->plugin_name ); ?>
    </label>
    <input type="text" id="wp_license_manager_product_file_name"
           name="wp_license_manager_product_file_name"
           value="<?php echo esc_attr( $product_meta['file_name'] ); ?>"
           size="25" />
</p>

قالب HTML نسبتا ساده است، یک سری از برچسب‌ها به وسیله عناصر ورودی با مقادیرشان از آرایه product_meta$ که از تابع بالا بازیابی کردیم، خوانده می‌شود.

حالا، با متاباکس ساخته شده، ذخیره داده در آن تامین می‌شود.

قدم سوم: ذخیره داده متاباکس
اگر تا اینجا دقت کرده باشید، برای توسعه پلاگین وردپرس و افزودن عملکردهای جدید، همیشه با پیدایش ترفند یا فیلتر مناسب برای آن شروع می‌شود.

این برای ذخیره داده متاباکس هم صدق می‌کند.

این بار عملیات قلاب زدن از تابع save_post انجام می‌‌شود. عملیاتی که با هر بار ذخیره شدن پست‌ها در بخش مدیریت وردپرس فعال می‌شود. دوباره، در کلاس Wp_License_Manager و به تابع ()define_admin_hooks یک خط جدید اضافه کنی:

$this->loader->add_action( 'save_post', $plugin_admin, 'save_product_information_meta_box' );

تابع، save_product_information_meta_box، داخل کلاس Wp_License_Manager_Admin قرار می‌گیرد:

/**
 * Saves the product information meta box contents.
 *
 * @param $post_id  int     The id of the post being saved.
 */
public function save_product_information_meta_box( $post_id ) {
    if ( ! $this->is_nonce_ok( 'product_meta_box' ) ) {
        return $post_id;
    }
 
    // Ignore auto saves
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
        return $post_id;
    }
 
    // Check the user's permissions
    if ( !current_user_can( 'edit_posts', $post_id ) ) {
        return $post_id;
    }
 
    // Read, sanitize, and store user input
    $meta = get_post_meta( $post_id, 'wp_license_manager_product_meta', true );
    if ( $meta == '' ) {
        $meta = array();
    }
 
    $meta['file_bucket'] = sanitize_text_field( $_POST['wp_license_manager_product_bucket'] );
    $meta['file_name'] = sanitize_text_field( $_POST['wp_license_manager_product_file_name'] );
    $meta['version'] = sanitize_text_field( $_POST['wp_license_manager_product_version'] );
    $meta['tested'] = sanitize_text_field( $_POST['wp_license_manager_product_tested'] );
    $meta['requires'] = sanitize_text_field( $_POST['wp_license_manager_product_requires'] );
    $meta['updated'] = sanitize_text_field( $_POST['wp_license_manager_product_updated'] );
    $meta['banner_low'] = sanitize_text_field( $_POST['wp_license_manager_product_banner_low'] );
    $meta['banner_high'] = sanitize_text_field( $_POST['wp_license_manager_product_banner_high'] );
 
    // Update the meta field
    update_post_meta( $post_id, 'wp_license_manager_product_meta', $meta );
}

بیایید از طریق تابع بفهمیم چه کاری انجام می‌دهد:

خط ۷ تا ۹: اگر به یاد داشته باشید،یک فیلد موقتی درست قبل‌از تفسیر محصول متاباکس اضافه کردیم. در این تابع، ما از همان فیلد موقتی برای تایید کاربری که داده را از آن فرم ارسال می‌کند استفاده می‌کنیم( بزودی تابع is_nonce_ok را اضافه خواهید کرد).

خط ۱۱ تا ۱۴: داده متاباکس را زمانی که وردپرس درحال ذخیره خودکار است، ذخیره نمیکند. به این دلیل که، پیشفرض وردپرس داده متاباکس را نمی‌پذیرد، زمانی که یک AJAX را فرامی‌خواند تا ذخیره خودکار را انجام دهد، و سپس بروزرسانی داده متاباکس پر می‌شود.

خط ۱۶ تا ۱۹: اگر کاربر توانایی ویرایش پست‌ها را داشته باشد، اجازه دخیره داده‌ها را می‌دهد. افزودن یک قابلیت سفارشی برای ویرایش محصولات مدیریت لایسنس جزو مواردی است که در آینده به آن می‌رسیم.

خط ۲۲ تا ۲۵: فراداده محصول موجود را خوانده، یا اگر هنوز فراداده‌ای ذخیره نشده، یک داده آرایه‌ای جدید را ایجاد می‌کند( get_post_meta یک رشته خالی را برمی‌گرداند اگر عنصری از فرا داده پیدا نشود و پارامتر سوم در حالت true باشد.

خط ۲۷ تا ۳۴: داده ارسال شده را می‌پذیرد، بعضی از بهسازی‌های اصلی را انجام می‌دهد.

خط ۳۷: همه چیز را قبول کرده، داده را ذخیره می‌کند.

حالا، قبل از اینکه سراغ لایسنس‌ها برویم، یک کار دیگر هم انجام دهید. توابع کمکی برای تفسیر و بازبینی متاباکس موقتی را اضافه کنید.

اول، ایجاد کنید:

/**
 * A helper function for creating and rendering a nonce field.
 *
 * @param   $nonce_label  string  An internal (shorter) nonce name
 */
private function render_nonce_field( $nonce_label ) {
    $nonce_field_name = $this->plugin_name . '_' . $nonce_label . '_nonce';
    $nonce_name = $this->plugin_name . '_' . $nonce_label;
 
    wp_nonce_field( $nonce_name, $nonce_field_name );
}

کار اصلی این تابع بازخوانی wp_nonce_field است که کار ساخت توکن‌های یک بار مصرف موقتی را انجام داده و آن را در یک فیلد مخفی HTML می‌نویسد.

سپس، بررسی:

/**
 * A helper function for checking the product meta box nonce.
 *
 * @param   $nonce_label string  An internal (shorter) nonce name
 * @return  mixed   False if nonce is not OK. 1 or 2 if nonce is OK (@see wp_verify_nonce)
 */
private function is_nonce_ok( $nonce_label ) {
    $nonce_field_name = $this->plugin_name . '_' . $nonce_label . '_nonce';
    $nonce_name = $this->plugin_name . '_' . $nonce_label;
 
    if ( ! isset( $_POST[ $nonce_field_name ] ) ) {
        return false;
    }
 
    $nonce = $_POST[ $nonce_field_name ];
 
    return wp_verify_nonce( $nonce, $nonce_name );
}

تابع بررسی موقتی از همان موارد تابع بالای استفاده کرده، و سپس از آنها برای بازیابی موقتی فرم داده فرستاده شده استفاده می‌کند( خط ۱۱ تا ۱۵ ). سپس، اگر پیدا شد، از تابع wp_verify_nonce وردپرس برای بررسی هماهنگی کد فرستاده شده با نمونه دخیره شده استفاده می‌کند( خط ۱۷ ).

۳- افزودن لایسنس‌ها

الان تقریبا نصف راه را از اولین آموزش از این مجموعه را سپری کرده‌ایم: محصولات در مکان خود مستقر شده‌اند و حالا نوبت بررسی لاسنس‌ها است.

یک لایسنس در ساده‌ترین حالت متشکل از دو عنصر است: یک کلید لایسنس و یک آی‌دی کاربر( از ایمیل به عنوان آی‌دی استفاده می‌کنیم ). برای کنترل بیشتر لایسنس، یک عنصر سومی هم اضافه می‌کنیم: تاریخ انقضا، تاریخی که لایسنس بعد از بروزرسانی از طرف سرور مدیریت لایسنس دریافت نمی‌کند.

ایجاد مدیر رابط کاربری برای لایسنس‌ها به همان سادگی است که برای محصولات ایجاد کردیم: یک لیستی از لایسنس‌ها و یک گزینه برای ایجاد نمونه جدید. البته اجرای آن کاملا متفاوت است: هنگامیکه یک محصول کمی به متافور پست شبیه باشد و سپس به طور طبیعی به شکل یک نوع پست سفارشی اجرا می‌شود، لایسنس‌ها با استفاده از جدول پایگاه‌داده خود بهترین اجرا را دارند.

قدم اول: ایجاد یک جدول پایگاه داده
ساخت عملکرد لایسنس‌ها با ایجاد یک جدول پایگاه‌داده که لایسنس‌ها را نگهداری می‌کند، شروع می‌شود. در اکثر مواقع ایجاد جدول پایگاه‌داده در فعالسازی پلاگین است، قبل از اینکه کاربر هرگونه تلاشی برای ایجاد جدول انجام دهد.

قالب استاندار پلاگین وردپرس با یک تابع خالی که می‌توانید کد خود را در آن بنویسید، کار را آسان کرده است. تابع activate، در کلاس Wp_License_Manager_Activator، هر زمان که برروی Activate در منوی پلاگین کلیک کنید یا زمانیکه بروزرسانی تمام شود، بیانگر فعال بودن پلاگین است.

اول، متغیر تعریف شده زیر را به بالای کلاس خود اضافه کنید:

/**
 * The database version number. Update this every time you make a change to the database structure.
 *
 * @access   protected
 * @var      string    $db_version   The database version number
 */
protected static $db_version = 1;

و سپس، تابع فعال‌سازی با کد زیر بروزرسانی می‌شود:

/**
 * Code that is run at plugin activation.
 */
public static function activate() {
    // Update database if db version has increased
    $current_db_version = get_option( 'wp-license-manager-db-version' );
    if ( ! $current_db_version ) {
        $current_db_version = 0;
    }
 
    if ( intval( $current_db_version ) < Wp_License_Manager_Activator::$db_version ) {
        if ( Wp_License_Manager_Activator::create_or_upgrade_db() ) {
            update_option( 'wp-license-manager-db-version', Wp_License_Manager_Activator::$db_version );
        }
    }
}

عملکرد تابع به شرح زیر است:

خط ۶ تا ۹: گزینه wp-license-manager-db-version را می‌پذیرد. ما از این گزینه برای ذخیره نسخه فعلی و فعال پایگاه‌داده پلاگین در سایت استفاده می‌کنیم.

خط ۱۱: نسخه فعلی پایگاه‌داده را بانمونه‌ای که در کد اصلی پلاگین تعریف کردیم، مقایسه می‌کند( db_version$، در بالا تعریف شده). اگر شماره نسخه کد پلاگین موجود بیشتر از نمونه ذخیره شده در گزینه‌های وردپرس باشد، پایگاه‌داده نیاز به بروزرسانی دارد.

خط ۱۲: بروزرسانی پایگاه داده را شروع می‌کند.

خط ۱۳: اگر بروزرسانی پایگاه‌داده موفقیت‌آمیز باشد، گزینه wp-license-manager-db-version را برای هماهنگ شدن با نسخه در کد، بروزرسانی می‌کند.

حالا، ما سیستمی برای نگهداری نسخه‌های پایگاه‌داده ایجاد کردیم و توانایی ایجاد جدول پایگاه داده را دارد. تابع زیر را به Wp_License_Manager_Activator اضافه کنید:

/**
 * Creates the database tables required for the plugin if 
 * they don't exist. Otherwise updates them as needed.
 *
 * @return bool true if update was successful.
 */
private static function create_or_upgrade_db() {
    global $wpdb;
 
    $table_name = $wpdb->prefix . 'product_licenses';
         
    $charset_collate = '';
    if ( ! empty( $wpdb->charset ) ) {
        $charset_collate = "DEFAULT CHARACTER SET {$wpdb->charset}";
    }
    if ( ! empty( $wpdb->collate ) ) {
        $charset_collate .= " COLLATE {$wpdb->collate}";
    }
 
    $sql = "CREATE TABLE " . $table_name . "("
         . "id mediumint(9) NOT NULL AUTO_INCREMENT, "
         . "product_id mediumint(9) DEFAULT 0 NOT NULL,"
         . "license_key varchar(48) NOT NULL, "
         . "email varchar(48) NOT NULL, "
         . "valid_until datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "updated_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
         . "UNIQUE KEY id (id)"
         . ")" . $charset_collate. ";";
 
    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );
 
    return true;
}

بیشتر این تابع در مورد ایجاد کوئری CREAT TABLE اس کیو ال است که از آن برای ایجاد جدول پایگاه‌داده استفاده می‌کنیم:

خط ۱۰: نامی برای جدول پایگاه‌داده در نظر می‌گیرد.

خط ۱۲ تا ۱۸: بعضی از تعاریف مجموعه کاراکترها که در آخر اس کیو ال استفاد می‌شود.

خط ۲۰ تا ۲۹: اس کی ال برای کوئری CREATE TABLE. جدول شامل موارد زیر است:

id: یک آی‌دی خاص برای هر ردیف.
product_id: آی‌دی برای اینکه بفهمیم محصول به کدام لایسنس پیوند داده شده.
license_key: کلید لایسنس به صورت رشته‌ای که به عنوان رمزعبور استفاده می‌شود.
email: آدرس ایمیل صاحب لایسنس، که به عنوان نام کاربری استفاده می‌شود.
valid_until: تاریخ انقضای لایسنس.
created_at: زمانی که لایسنس ایجاد شده.
updated_at: آخرین زمان بروزرسانی لایسنس.

خط ۳۱ تا ۳۲: از روش dbDelta برای ایجاد یا بروزرسانی جدول پایگاه‌دداده وردپرس استفاده می‌کند. توجه کنید که dbDelta در حقیقت کوئری CREATE TABLE را اجرا نمی‌کند، بلکه روی آن بررسس انجام داده و آنرا با ساختار فعلی جدول مقایسه کرده، سپس اصلاحات لازم را انجام می‌دهد.

پس،بعدا، اکر تصمیم به تغییر ساختار جدول گرفتید، به جای اینکه یک کوئری جدید اس کیو ال بنویسید، کافی است کوئری CREATE TABLE را ویرایش کرده، پارامتر db_version$ رابروزرسانی کنید، و کنترل کار را به dbDelta بسپارید.

برای اطلاعات بیشتر در مورد جداول پایگاه داده وردپرس و استفاده از dbDelta، مقاله ایجاد جداول با پلاگین‌ها که در وردپرس کدکس است مطالعه کنید.

بعدا اگر پلاگین را فعال کنید، یک جدول پایگاه‌داده برای لایسنس‌ها ایجاد می‌شود. اگر درحال حاضر پلاگین فعال است، نیاز است این کار را یک بار دیگر انجام دهید( غیرفعال کنید و سپس فعال کنید) تا پایگاه‌داده ایجاد شود.

قدم دوم: ایجاد صفحات منوی لایسنس

حال ما جدول پایگاه‌داده‌ای را برای ذخیره‌سازی لایسنس‌ها ایجاد کردیم، شروع به ساخت صفحات منو بکنید: قسمت Licenses و گزینه Add new.

دوباره، با قلاب زدن از تابع define_admin_hooks موجود در Wp_License_Manager شروع می‌کنیم:

$this->loader->add_action( 'admin_menu', $plugin_admin, 'add_licenses_menu_page' );

در زیر عملکر تابع add_license_menu_page را از طریق Wp_License_Manager_Admin مشاهده می‌کنید:

/**
 * Creates the settings menu and sub menus for adding and listing licenses.
 */
public function add_licenses_menu_page() {
    add_menu_page(
        __( 'Licenses', $this->plugin_name ),
        __( 'Licenses', $this->plugin_name ),
        'edit_posts',
        'wp-licenses',
        array( $this, 'render_licenses_menu_list' ),
        'dashicons-lock',
        '26.1'
    );
 
    add_submenu_page(
        'wp-licenses',
        __( 'Licenses', $this->plugin_name ),
        __( 'Licenses', $this->plugin_name ),
        'edit_posts',
        'wp-licenses',
        array( $this, 'render_licenses_menu_list' )
    );
 
    add_submenu_page(
        'wp-licenses',
        __( 'Add new', $this->plugin_name ),
        __( 'Add new', $this->plugin_name ),
        'edit_posts',
        'wp-licenses-new',
        array( $this, 'render_licenses_menu_new' )
    );
}

بیایید دقیق‌تر بررسی کنیم:

خط ۵ تا ۱۳: یک منوی سطح بالا با موضوع Licenses ایجاد می‌کند. تابع add_menu_page پارامترهای زیر را می‌گیرد:

۱- page_title$: موضوع صفحه منو( همان مقدار تگ title در HTML).
۲- menu_title$: موضوعی که روی صفحه نمایش داده می‌شود.
۳- capability$: توانایی مورد نیاز برای نمایش صفحه است. من از edit_posts استفاده کرده‌ام، اما در آینده، ترجیح می‌دهم توانایی‌های موردنیاز خودم را به آن اضافه کنم.
۴- menu_slug$: معرف صفحه منو، که در URL صفحه استفاده می‌شود.
۵- function$: تابعی که تفسیر صفحه منو را دردست دارد.
۶- icon_url$: این فیلد به روش‌های مختلفی استفاده می‌شود، ولی بنده آیکون‌های داشبورد را که جلوتر بیان کردم، انتخاب می‌کنم.
۷- position$: طریقه جایگیری آیتم‌های در منوی وردپرس را مشخص می‌کند. مشکلی که این پارامتر دارد، این است که اگر مقدار position$ دو آیتم یکی باشد، فقط یکی از آنها نمایش داده می‌شود. بر اساس مستندات وردپرس، با استفاده از یک عدد دسیمال، که در اینجا انجام دادیم، کمی مشکل برطرف می‌شود.

خط ۱۵ تا ۲۲: یک زیر منو برای لیست کردن لایسنس‌ها اضافه می‌کند. پارامترهای add_submenu_page همانند add_menu_page هستند با این تفاوت که پارامتر اول باید آی‌دی منوی بالایی که زیرمنو به آن اضافه می‌شود، باشد.

نکته قابل توجه این است که، عملکر زیر منوی اول مانند منوی بالایی است. عملی که زیرمنو با یک کلیک کاربر انجام می‌دهد درست همانند منوی سطح بالا است.

خط ۲۴ تا ۳۱: دومین زیرمنو منویی برای افزودن لایسنس جدید است.

برای اجرای کد بدون خطا، دو تابع خالی اضافه کنید:

public function render_licenses_menu_list() {
 
}
 
public function render_licenses_menu_new() {
 
}

قدم سوم: ایجاد صفحه افزودن لایسنس
با تنظیمات صفحات ایجاد شده، یک عملکرد به نام Add New License به صفحه اول اضافه کنید.

صحه مانند تصویر زیر است:

ایجاد لایسنس قالب وردپرس, ساخت لایسنس وردپرس, کد لایسنس برای قالب

همانظور که گفته شد، تابعی که تفسیر را برای Add new انجام می‌دهد render_licenses_menu_new گفته می‌شود. خود تابع ساده است، اکثر خطوط آن صرف سکونت یک لیست از محصولات که برای تفسیر لیست بازشو استفاده شده، می‌شود.

/**
 * Renders the list add new license menu page using 
 * the "licenses_new.php" partial.
 */
public function render_licenses_menu_new() {
    // Used in the "Product" drop-down list in view
    $products = get_posts(
        array(
            'orderby'           => 'post_title',
            'order'             => 'ASC',
            'post_type'         => 'wplm_product',
            'post_status'       => 'publish',
            'nopaging'          => true,
            'suppress_filters'  => true
        )
    );
 
    require plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/licenses_new.php';
}

خط ۷ تا ۱۶: تمام پست‌های منتشر شده نوع سفارشی wplm_product را بازیابی می‌کند.

خط ۱۸: شامل محتوای مختصری از HTML برای این صفحه منو است.

در زیر درون قالب HTMLرا مشاهده می‌کنید:

<?php
/**
 * The view for the admin page used for adding a new license.
 *
 * @package    Wp_License_Manager
 * @subpackage Wp_License_Manager/admin/partials
 */
?>
<div class="wrap">
    <div id="icon-edit" class="icon32 icon32-posts-post"></div>
 
    <h2><?php _e( 'Add New License', $this->plugin_name ); ?></h2>
    <p>
        <?php
            $instructions = 'Use this form to manually add a product license. '
                . 'After completing the process, make sure to pass the license key to the customer.';
 
            _e( $instructions, $this->plugin_name );
        ?>
    </p>
 
    <form action="<?php echo admin_url( 'admin-post.php' ); ?>" method="post">
        <?php wp_nonce_field( 'wp-license-manager-add-license', 'wp-license-manager-add-license-nonce' ); ?>
        <input type="hidden" name="action" value="license_manager_add_license">
 
        <table class="form-table">
            <tr class="form-field form-required">
                <th scope="row">
                    <label for="email">
                        <?php _e( 'Email', $this->plugin_name ); ?>
                        <span class="description"><?php _e( '(required)', $this->plugin_name ); ?></span>
                    </label>
                </th>
                <td>
                    <input name="email" type="text" id="email" aria-required="true">
                </td>
            </tr>
            <tr class="form-field form-required">
                <th scope="row">
                    <label for="email">
                        <?php _e( 'Product', $this->plugin_name ); ?>
                        <span class="description"><?php _e( '(required)', $this->plugin_name ); ?></span>
                    </label>
                </th>
                <td>
                    <select name="product" id="product" aria-required="true">
                        <?php foreach ( $products as $product ) : ?>
                            <option value="<?php echo $product->ID; ?>"><?php echo $product->post_title; ?></option>
                        <?php endforeach; ?>
                    </select>
                </td>
            </tr>
            <tr class="form-field form-required">
                <th scope="row">
                    <label for="valid_until">
                        <?php _e( 'Valid until', $this->plugin_name ); ?>
                    </label>
                </th>
                <td>
                    <input name="valid_until" type="text" id="valid_until" aria-required="false" />
                    <p class="description">
                        <?php _e( '(Format: YYYY-MM-DD HH:MM:SS / Leave empty for infinite)', $this->plugin_name );?>
                    </p>
                </td>
            </tr>
        </table>
 
        <p class="submit">
            <input type="submit" name="add-license" class="button button-primary"
                   value="<?php _e( 'Add License', $this->plugin_name ); ?>" >
        </p>
    </form>
 
</div>

این تقریبا یک فرم اصلی است، که کلاس‌های CSS استفاده می‌کند که تعریف شده برای اینکه مدیر وردپرس به همه چیز مسلط باشد.

بعضی از خطوط که باید به آنها توجه شود عبارتنداز:

خط ۲۲: زمانی که کاربر فرم را ارائه می‌دهد، فرم مورد نظر به admin-post.php وردپرس ارسال می‌شود.

خط ۲۳: درست شبیه متاباکس، بررسی موقتی انجام می‌دهد تا از فردی که لایسنس اضافه می‌کند، مطمئن شود که از این صفحه استفاده می‌کند.

خط۲۴ : یک فیلد مخفی با نام action و مقدار ‘license_manager_add_license’ تعریف می‌کند. این فیلد برای افزودن یک تابع کنترلی برای واگذاری فرم استفاده شده است.

قدم چهارم: ذخیره لایسنس

در قدم قبلی، فرم Add New License را ایجاد کردیم. حالا نوبت ایجاد عملکردی برای ذخیره‌سازی است.

به تابع define_admin_hooks در Wp_License_Manager برگردید و یک عمل جدید به آن اضافه کنید:

$this->loader->add_action( 'admin_post_license_manager_add_license', $plugin_admin, 'handle_add_license' );

این دفعه، از admin_post_{action} استفاده می‌کنیم، که یک عمل هوشمند برای کنترل فرم‌های سفارشی است.

زمانی که یک فرم با فیلد مخفی action ارسال شود، وردپرس مقدار فیلد را بررسی کرده و از ایجاد آن برای بازخوانی یک عمل منطبق استفاده می‌کند. مقداری که در فیلد قرار دادیم “license_manager_add_license” بود پس می‌توانیم یک عمل با نام admin_post_license_manager_add_license را اضافه نماییم.

در زیر تابع handle_add_license را در Wp_License_Manager_Admin می‌بینید:

/**
 * Handler for the add_license action (submitting 
 * the "Add New License" form).
 */
public function handle_add_license() {
    global $wpdb;
 
    if ( ! empty( $_POST )
        && check_admin_referer( 'wp-license-manager-add-license', 
            'wp-license-manager-add-license-nonce' ) ) {
 
        // Nonce valid, handle data
 
        $email = sanitize_text_field( $_POST['email'] );
        $valid_until = sanitize_text_field( $_POST['valid_until'] );
        $product_id = intval( $_POST['product'] );
         
        $license_key = wp_generate_password( 24, true, false );
 
        // Save data to database
        $table_name = $wpdb->prefix . 'product_licenses';
        $wpdb->insert(
            $table_name,
            array(
                'product_id' => $product_id,
                'email' => $email,
                'license_key' => $license_key,
                'valid_until' => $valid_until,
                'created_at' => current_time( 'mysql' ),
                'updated_at' => current_time( 'mysql' )
            ),
            array(
                '%d',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s'
            )
        );
 
        // Redirect to the list of licenses for displaying the new license
        wp_redirect( admin_url( 'admin.php?page=wp-licenses' ) );
    }
}

بیایید ببینیم تابع چه عملی انجام می‌دهد:

خط ۸ تا ۱۰: فرمان بررسی موقتی را به فرم HTML اضافه می‌کند.

خط ۱۴ تا ۱۶: داده لایسنس ارائه شده را مطابق اصول جمع‌اوری می‌کند.

خط ۱۸: یک کلید لایسنس تولید می‌کند. در این پلاگین، ما از کلید لایسنس به عنوان رمزعبور استفاده می‌کنیم که همیشه با آدرس ایمیل کاربر همراه است، بنابراین بنده تصمیم گرفتم که کلیدهای لایسنس خاص نیاز نیست. تابع تولید رمزعبور وردپرس راه ساده‌ای برای ایجاد رمزعبور تصادفی است – شاید همیشه امن‌ترین راه نباشد اما به اندازه کافی خوب است.

خط ۲۱ تا ۴۰: داده را در جدول پایگاه‌داده ذخیره می‌کند. اولین پارامتر برای تابع insert درwpdb$ نام جدول است. دومین پارامتر آرایه‌ای از ستون‌های پایگاه‌داده با مقادیرشان است. سومین پارامتر انواع پارامترها را برای قالب‌بندی کوئری مشخص می‌کند( s% رشته‌ای از مقادیر عددی و نقل‌قول را مشخص می‌کند که با d% بدون نقل‌قول گذاشته می‌شود).

خط ۴۳: کاربر را به لیست لایسنس راهنمایی می‌کند. در ادامه آنرا خواهیم ساخت.

۴- لیست لایسنس‌ها

حالا تعدادی داده ذخیره‌شده برای لایسنس‌ها داریم، حالا نوبت قدم آخر در این آموزش است: ساخت یک لیست برای مرور لایسنس‌ها.

ایجاد لایسنس قالب وردپرس, ساخت لایسنس وردپرس, کد لایسنس برای قالب

من همیشه دوست دارم ظاهر رابط کاربری مدیر را خیلی شبیه به مدیر خود وردپرس ایجاد کنم، و سپس، زمان ایجاد این لیست، تصمیم گرفتم تا از همان کدهای هسته وردپرس برای تفسیرشان استفاده کنم: کلاس Wp_List_Table، به عنوان کلاس اصلی برای نمایش یک لیست از عناصر در یک جدول HTML ای‌ژکس‌شده در مستندات PHPDoc خودش است.

این کلاس ایجاد جداول لیست با ظاهری زیبا را خیلی آسان کرده است، مانند یک نمونه‌ای که در قسمت بالای وردپرس مشاهده می‌کنید، اما با کمی احتیاط:

توسعه‌دهندگان وردپرس این کلاس را به عنوان private@ نوشته‌اند، بدین منظور که آنها هرزمان که بخواهند حق تغییر آنرا از ریشه دارند. به عبارت دیگر، استفاده از کلاس یک خطر است و به همین سبب شما مجبور خواهید بود قبل از انتشار هرگونه وردپرسی، پلاگین خود را آزمایش کرده، تا از صحت لیست‌ها اطمینان پیدا کنید.

اگر فکر می‌کنید خطر آن بالاست، گزینه دیگری هم وجود دارد: نسخه اخیر کلاس را در پروژه‌تان کپی کرده، تغییر نام دهید و از آن فایل کپی شده به عنوان کلاس اصلی لیست استفاده کنید. در پایان، من تصمیم گرفتم تا گزینه‌های فایل کپی‌شده را خودم بررسی کرده، تا از اجرای آن در آینده اطمینان حاصل کنم.

قدم اول: ایجاد کلاس جدول لیست

ابتدا، کلاس Wp_List_Table را پیدا کرده( این کلاس درفایل wp-admin/includes/class-wp-list-table.php است) و یک نسخه از آن را در پروژه خود کپی کنید. کلاس و فایل کپی‌شده را تغییر نام دهید تا با کلاس اصلی هسته وردپرس ناسازگار نباشد( برای مثال Wp_License_Manager_List_Table).

سپس، برای توسعه کلاس اصلی یک کلاس از روی کلاس خود ایجاد کنید. کلاس License_List_Table در پوشه مدیر قرار دهید. سپس خطوط require_once زیر را به تابع load_dependencies در Wp_License_Manager اضافه کنید:

/**
 * The classes responsible for rendering the list of licenses.
 */
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-license-manager-list-table.php';
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-licenses-list-table.php';

کلاس Licenses_List_Table که جدیدا ایجاد کردید را باز کنید، و یک سازنده به عنوان پارامتر دامنه و یک فیلد برای ذخیره مقدار اضافه کنید. این قطعه کد نیاز به توضیح ندارد:

class Licenses_List_Table extends Wp_License_Manager_List_Table {
 
    /**
    * The plugin's text domain.
    * 
    * @access  private
    * @var     string  The plugin's text domain. Used for localization.
    */
    private $text_domain;
 
    /**
     * Initializes the WP_List_Table implementation.
     *
     * @param $text_domain  string  The text domain used for localizing the plugin.
     */
    public function __construct( $text_domain ) {
        parent::__construct();
 
        $this->text_domain = $text_domain;
    }
     
}
قدم دوم: تعیین ستون‌های لیست
Wp_List_Table دارای مجموعه‌ای از توابع است که می‌توان از آنها برای تعیین داده و قوانین قابل‌بندی لیست‌ها صرف نظر کرد.

بیایید از تعیین ستون‌های لیست، ترتیب آنها، و سرتیتر هر ستون شروع کنید. تابع زیر را به کلاس Licenses_List_Table اضافه کنید.

/**
 * Defines the database columns shown in the table and a 
 * header for each column. The order of the columns in the 
 * table define the order in which they are rendered in the list table.
 *
 * @return array    The database columns and their headers for the table.
 */
public function get_columns() {
    return array(
        'license_key' => __( 'License Key', $this->text_domain ),
        'email'       => __( 'Email', $this->text_domain ),
        'product_id'  => __( 'Product', $this->text_domain ),
        'valid_until' => __( 'Valid Until', $this->text_domain ),
        'created_at'  => __( 'Created', $this->text_domain )
    );
}

توجه داشته باشید که کلید‌های آرایه باید همنام با نام ستون‌های جدول پایگاه‌داده باشند.

اگر نمی‌خواهید ستون created_at نمایش داده شود،‌می‌توانید با استفاده از تابع get_hidden_columns آنرا مخفی کنید:

/**
 * Returns the names of columns that should be hidden from the list table.
 * 
 * @return array    The database columns that should not be shown in the table.
 */
public function get_hidden_columns() {
    return array( 'created_at' );
}

تعیین ستون‌هایی که برای مرتب‌سازی داده لیست استفاده می‌شوند مشابه با روش زیر است:

/**
 * Returns the columns that can be used for sorting the list table data. 
 * 
 * @return array    The database columns that can be used for sorting the table.
 */
public function get_sortable_columns() {
    return array(
        'email' => array( 'email', false ),
        'valid_until' => array( 'valid_until', false )
    );
}

سپس، نگاهی به قالب‌بندی داده‌های ستون بیاندازید. قالب‌بندی به دو روش انجام می‌شود: هم با تعیین تابع قالب‌بندی سفارشی با نام column_{column_name} که به جای column_name نام ستونی که در بالای get_columns لیست‌شده قرار می‌گیرد، و هم می‌توان از تابع مفسر پیش‌فرض column_default استفاده کرد.

از column_default که به سادگی قابل اجرا است، برای ستون‌ها استفاده کنید. این تابع دو پارامتر دریافت می‌کند: ردیف‌ پایگاه‌داده که توسط item$ و نام ستون که توسط column_name$ کنترل می‌شوند.

/**
 * Default rendering for table columns.
 *
 * @param $item         array   The database row being printed out.
 * @param $column_name  string  The column currently processed.
 * @return string       The text or HTML that should be shown for the column.
 */
function column_default( $item, $column_name ) {
    switch( $column_name ) {
        case 'email':
        case 'created_at':
            return $item[$column_name];
 
        default:
            break;
    }
 
    return '';
}

سپس، یک نمونه از توابع خروجی سفارشی را مشاهده می‌کنید. به کد اصلی پلاگین دقت کنید، می‌بینید که گروهی از آنها را ایجاد کرده‌ام.

در زیر مثالی برای مفسر ستون valid_until مشاهده می‌کنید:

/**
 * Custom renderer for the valid_until field.
 *
 * @param $item     array   The database row being printed out.
 * @return string   The text or HTML that should be shown for the column.
 */
function column_valid_until( $item ) {
    $valid_until = $item['valid_until'];
 
    if ($valid_until == '0000-00-00 00:00:00') {
        return __( 'Forever', $this->text_domain );
    }
 
    return $valid_until;
}

این مفسر زمانی‌که مقدار فیلد ‘0000-00-00 00:00:00’ باشد “Forever” نمایش می‌دهد وگرنه مقدار خود آن را برمی‌گرداند.

قدم سوم: داده‌های لیست کوئری
حال که تنظیمات تفسیر را برای لیست تعیین کردیم، تعدادی داده به ایت ترکیب اضافه کنید. این عمل را prepare_items در تابع Wp_List_Table انجام داده است.

در زیر تابع را مشاهده می‌کنید:

/**
 * Populates the class fields for displaying the list of licenses.
 */
public function prepare_items() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'product_licenses';
 
    $columns = $this->get_columns();
    $hidden = $this->get_hidden_columns();
    $sortable = $this->get_sortable_columns();
 
    $this->_column_headers = array( $columns, $hidden, $sortable );
 
    // Pagination
    $licenses_per_page = 20;
    $total_items = $wpdb->get_var( "SELECT COUNT(id) FROM $table_name" );
 
    $offset = 0;
    if ( isset( $_REQUEST['paged'] ) ) {
        $page = max( 0, intval( $_REQUEST['paged'] ) - 1 );
        $offset = $page * $licenses_per_page;
    }
 
    $this->set_pagination_args(
        array(
            'total_items' => $total_items,
            'per_page' => $licenses_per_page,
            'total_pages' => ceil( $total_items / $licenses_per_page )
        )
    );
 
    // Sorting
    $order_by = 'email'; // Default sort key
    if ( isset( $_REQUEST['orderby'] ) ) {
        // If the requested sort key is a valid column, use it for sorting
        if ( in_array( $_REQUEST['orderby'], array_keys( $this->get_sortable_columns() ) ) ) {
            $order_by = $_REQUEST['orderby'];
        }
    }
 
    $order = 'asc'; // Default sort order
    if ( isset( $_REQUEST['order'] ) ) {
        if ( in_array( $_REQUEST['order'], array( 'asc', 'desc' ) ) ) {
            $order = $_REQUEST['order'];
        }
    }
 
    // Do the SQL query and populate items
    $this->items = $wpdb->get_results(
        $wpdb->prepare( "SELECT * FROM $table_name ORDER BY $order_by $order LIMIT %d OFFSET %d", $licenses_per_page, $offset ),
        ARRAY_A );
}

بیایید این تابع را بررسی کینم:

خط ۸ تا ۱۲: با استفاده از تابعی که در بالا ایجاد کردیم، سرتیتر ستون‌ها را جمع آوری کرده و اطلاعات را مرتب می‌کند.

قسمت باقی‌مانده بعد از آن داده را جستجو می‌کند.

خط ۱۵ تا ۲۲: اطلاعات صفحه‌بندی را محاسبه می‌کند. اگر کاربر یک صفحه را درخواست کرده باشد، پارامتر page شماره صفحه را می‌گیرد( از یک شروع می‌شود)، بنابراین می‌توانیم از آن برای محاسبه آفست برای کوئری SQL استفاده کنیم.

خط ۲۴ تا ۳۰: اطلاعات صفحه‌بندی را برای جدول لیست ارسال می‌کند پس میتواند دکمه‌های جهت‌یابی صحیح را هنگام تفسیر جدول نشان دهد.

خط ۳۳ تا ۴۶: ستون‌ها را آماده کرده و بر اساس ورودی کاربر مرتب می‌کند.

خط ۴۹ تا ۵۱: از متغیر‌های از پیش تعریف‌شده در تابع استفاده می‌کند تا جستجوی پایگاه‌داده را انجام داده، و در متغیر items$ کلاس قرار می‌گیرد.

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

قدم چهارم: استفاده از جدول لیست
قبلا در این آموزش، ما یک تابع خالی برای نمایش محتویات صفحه لایسنس ایجاد کردیم. حالا هم جدول لیست ایجاد کرده‌ایم، میتوانیم آن تابع را با render_licenses_menu_list که در Wp_License_Manager_Admin است پر کرده و سرانجام لایسنس‌ها را نمایان کنیم:

/**
 * Renders the list of licenses menu page using the "licenses_list.php" partial.
 */
public function render_licenses_menu_list() {
    $list_table = new Licenses_List_Table( $this->plugin_name );
    $list_table->prepare_items();
 
    require plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/licenses_list.php';
}

این تابع ابتدا Licenses_List_Table را جایگزین کلاسمان کرده سپس تابع prepare_item خود را فراخوانده تا داده‌ها را مقدار‌دهی اولیه کند، و در آخر یک قالب HTML برای تفسیر صفحه قرار دارد.

همچنین این قالب list_table->diplay$ را فرامی‌خواند، تا لیست موجود در صفحه را تفسیر کند.

<?php
/**
 * The view for the admin page used for listing licenses.
 *
 * @package    Wp_License_Manager
 * @subpackage Wp_License_Manager/admin/partials
 */
?>
 
<div class="wrap">
    <h2>
        <?php _e( 'Licenses', $this->plugin_name ); ?>
        <a class="add-new-h2" href="<?php echo admin_url( 'admin.php?page=wp-licenses-new' );?>">
            <?php _e( 'Add new', $this->plugin_name ) ?>
        </a>
    </h2>
 
    <?php $list_table->display(); ?>
</div>

در آینده چه یاد خواهید گرفت؟

هم‌اکنو ما یک پلاگین اصلی برای مرتب‌سازی محصولات و لایسنس‌ها داریم. اگرچه این پایان کار نیست.

در قسمت دوم این مجموعه آموزشی،به کار کردن رو پلاگین ادامه می‌دهیم و آنرا با یک API توسعه داده تا پلاگین‌ها و قالب‌ها توانایی بررسی لایسنس کاربر و دانلود بروزرسانی‌ها را داشته باشند.

در قسمت بعد با شما همراه هستیم!

نظرات کاربران (0)