Mục đích: Tạo ra một Addon có chức năng không cho thành viên thay đổi chữ ký khi có số post nhỏ hơn số post quy định. Sau đó có thể phát triên thêm các tùy chọn cho Addon này như thêm tùy chọn về nhóm. Đặt tên Addon này tên là ghChuky.

Trước mắt tạo ra phiên bản đơn giản đầu tiên Version 1.0: Tất cả các thành viên chưa đủ 10 post thì không được ký.

Bước 1. Chuẩn bị môi trường, tạo tên Addon và Listener

Bạn cần chuyển sang chế độ Debug Mode để phát triển Addon, làm điều này bằng cách thay đổi file config.php.

Mở file library/config.php và thêm vào cuối đoạn mã:

$config['debug'] = true;

Ghi lại thay đổi và đăng nhập vào trang AdminCP của XF, lúc này sẽ xuất hiện thêm mục Development.

Trang Development của XenForo

Màn hình trang Developement

Bạn chọn mục 

Development › Create Add-on

Bạn nhập các thông tin vào như sau:

  • Add-on ID: ghChuky
  • Title (Tiêu đề): Giới hạn chữ ký cho thành viên mới
  • Version String: 1.0
  • Version ID: 1

Nhập xong bấm vào Save Add-on lại

Tìm class được gọi để tạo Listener tương ứng

Mục đích là không cho thành viên mới tạo chữ ký, do đó cần xác định nơi mà thành viên cập nhật chữ ký trong XF, sau đó chúng ta tạo Listen để bắt sự kiện này. Các hoạt động này được điều khiển bởi Controller.

Các Controller trong XenForo: XF lập được lập trình theo mô hình MVC, sử dụng ZF, trong XF có bốn loại controller tương ứng trong các thư mục

Library/XenForo/ControllerAdmin
Library/XenForo/ControllerHelper
Library/XenForo/ControllerPublic
Library/XenForo/ControllerResponse

Controller khi soạn thảo chữ ký:  Điều khiển chỉnh sửa chữ ký nằm trong controller Public. Bạn mở thư mục ControllerPublic ra kiểm tra nhé. Bạn kiểm tra trong diễn đàn thấy URL để thành viên soạn thảo chữ ký có dạng ...account/signature, như vây bạn trở lại thư mục ControllerPublic tìm tới file có tên Account.php, các chức năng về chữ ký nằm trong này rồi. Mở file này ra tìm signature, tới hàm actionSignature(), đây chính là hàm bạn cần đè (quá tải - override).

Như vậy bạn thấy hàm, lớp bạn cần lắng nghe nằm trong đường dẫn:

Library/Xenforo/ControllerPublic/Acount.php

Theo cách viết code của ZF1 ứng dụng trong XF thì lớp đó là:

XenForo_ControllerPublic_Account

Hãy nhớ tên lớp này, để cần dùng về sau

Bước 2) Tạo Listener cho sự kiện

Trở lại AdminCP, bạn đến mục 

Development › Code Event Listeners

rồi bấm vào mục 

Create New Code Event Listener

Bạn sẽ tạo ra Listener ngồi lắng nghe các sự kiện mà XF gửi đến cho nó. Ở đây bạn nhiều tùy chọn loại sự kiện nó lắng nghe, với Addon này bạn lắng nghe sự kiện khi Controller được gọi, vậy Listen Event bạn chọn là 

Load_Class_Controller

Tạm thời bạn để trang này ở đây vì chưa save lại được, bạn cần tạo ra lớp và hàm sử lý sự kiên khi nó nghe thấy, rồi điền vào ở đây.

Bạn mở thư mục chứa code XF của bạn, mở thư mục /library/ ra. Ở đây bạn sẽ tạo ra cấu trúc thư mục cho Addon của bạn. 

Bạn tạo thư mục có tên GhChuky (chú ý tên giống với tên Addon - với chữ đầu viết hoa để theo cấu trúc thư viện XF).

Trong thư mục này, tạo ra một thư mục có tên là Listener.  Bên trong thư mục Listener tạo ra file php có tên: LoadClassController.php.  Tạm thời bạn chèn nội dung sau vào file đó:

<?php
class GhChuky_Listener_LoadClassController
{
        public static function loadClassListener($class, &$extend)
        { 
                if ($class == 'XenForo_ControllerPublic_Account')
                {
                        $extend[] = 'GhChuky_ControllerPublic_GhChuky';
                }

        }
}

Lưu ý là tên lớp và cấu trúc thư mục tương ứng, điều này rất quan trọng. 

$extend[] là mảng tại đó sẽ thêm tên lớp được gọi nếu như $class chứa XenForo_ControllerPublic_Account. (Có nghĩa sự kiện khi member vào soạn chữ ký - xem lại phần trên để rõ).

Giờ bạn trở lại phần Create New Code Event Listener và tiến hành điền lớp, method cho nó ở mục Execute Callback:

Class: GhChuky_Listener_LoadClassController
Method: loadClassListener 

Chú ý chọn Enable Callback Execution. Ở phần Description có thể ghi 'Lắng nghe sự kiện thành viên soạn thảo chữ ký'. Cuối cùng ở mục Add-on chọn tên bạn tạo ra ở trên, rồi save lại.

Đến giờ thì file LoadClassController.php của bạn đang lắng nghe tất cả các sự kiện liên quan tới load controller của XenForo, và ghi gặp load XenForo_ControllerPublic_Account thì nó gắp sự kiện cần xử lý tiếp với lớp 

GhChuky_ControllerPublic_GhChuky.

Bước 3) Quá tải Action của Controller trong XenForo

Tiếp theo ta lại phải tạo ra GhChuky_ControllerPublic_GhChuky. Bạn lại tạo file php sau:

GhChuky/ControllerPublic/GhChuky.php

Và thêm đoạn mã cần quá tải hành đồng sửa chữ ký vào, như sau:

<?php
class GhChuky_ControllerPublic_GhChuky extends XFCP_GhChuky_ControllerPublic_GhChuky{
    public function actionSignature()
    {        
    }
}

Chú ý tiền tố XFCP_  là bắt buộc.  Trong lớp này bạn đã quá tải hàm actionSignature() trong hàm này bạn tiến hành kiểm tra số lượng post của thành viên và các điều kiện khác để quyết định có cho soạn thảo chữ ký hay không.

Với cách làm này, hàm actionSignature() trong Account.php không được gọi nữa, thay vào đó nó chỉ gọi hàm actionSignature() trong 

GhChuky/ControllerPublic/GhChuky.php.

Bạn có thể copy toàn bộ code actionSignature() trong Account.php sang GhChuky.php và chỉnh sửa tại đây. Sau khi copy thì nội dung nó như GhChuky.php như sau:

<?php
class GhChuky_ControllerPublic_GhChuky extends XFCP_GhChuky_ControllerPublic_GhChuky{

    public function actionSignature()
    {
        
        if (!XenForo_Visitor::getInstance()->canEditSignature())
        {
            return $this->responseNoPermission();
        }
        
        $sigPerms = array();
        $visitor = XenForo_Visitor::getInstance();
        
        if ($visitor['message_count'] < 20)
        {          
            return $this->responseError('Bạn phải đủ 10 bài viết mới được ký;)');
        }


        $sigPerms['basic'] = $visitor->hasPermission('signature', 'basicText');
        $sigPerms['extended'] = $visitor->hasPermission('signature', 'extendedText');
        $sigPerms['align'] = $visitor->hasPermission('signature', 'align');
        $sigPerms['indent'] = $visitor->hasPermission('signature', 'align');
        $sigPerms['smilies'] =  $visitor->hasPermission('signature', 'maxSmilies') != 0;
        $sigPerms['link'] = $visitor->hasPermission('signature', 'link') && $visitor->hasPermission('signature', 'maxLinks');
        $sigPerms['image'] = $visitor->hasPermission('signature', 'image') && $visitor->hasPermission('signature', 'maxImages');
        $sigPerms['media'] = $visitor->hasPermission('signature', 'media');
        $sigPerms['block'] = $visitor->hasPermission('signature', 'block');
        $sigPerms['list'] = $visitor->hasPermission('signature', 'list');

        return $this->_getWrapper(
            'account', 'signature',
            $this->responseView(
                'XenForo_ViewPublic_Account_Signature',
                'account_signature',
                array('sigPerms' => $sigPerms)
            )
        );
    }
}

Giờ bạn tiếp tục điều chỉnh mã, thêm vào đoạn code kiểm tra nếu thành viên đó không đủ 10 post thì không được ký.

Ở đoạn code trên, sau dòng 

$visitor = XenForo_Visitor::getInstance();

bạn thêm đoạn mã sau:

if ($visitor['message_count'] < 20)
{          
  return $this->responseError('Bạn phải đủ 10 bài viết mới được ký;)');
}

Giờ thì bạn đã có một Addon chạy được rồi. Bạn có thể vào Export Addon này, và gộp file xml và các file nguồn vừa rồi mang đi cài đặt chỗ khác như Addon thông thường.

Bạn có thể tải về Addon trên để cài đặt hoặc nghiên cứu: addon-ghchuky1.0.zip

Nâng cấp lên V2.0

Giờ nâng cấp Addon bằng cách thêm chức năng thiết lập số số lượng bài post cần kiểm tra và chọn nhóm user cần kiểm tra khi ký.

Trước tiên tạo ra Option Group: Chọn AdminCP Home -> Options

Rồi chọn + Add Option Group, bảng thông tin bạn điền các thông số:

Group ID: ghChukyOption; Title: Tùy chọn chữ ký

Phần Add-on: chọn đúng tên Add-on đang làm. Cuối cùng Save lại

Đến đây ta có bảng option trong AdminCP, giờ chọn các option chi tiết trong nó.

tuy chon chu ky

Thêm tùy chọn số lượng bài post nhỏ nhất được ký

Mở lại Option Group vừa tạo ra, sau đó chọn Add Option, điền các thông tin sau:

  • Option ID: ghChuky_msgcount

ghChuky_msgcount là ID cần nhớ để truy cập lấy thông tin trong Code Addon của bạn. Phần Add on chọn đúng Addon của bạn. Phần Title có thể điền Bài viết tối thiểu để ký.

  • Edit Format: Spin Box
  • Format Parameters: 
Min=0
Max=50
Step=5
  • Data Type: Unsigned Interger
  • Default Value: 5

Các chỗ khác để mặc định như vậy, Save lại.

Thêm tùy chọn về nhóm User

Làm tương tự, với trường hợp này kiểu dữ liệu không phải là một số nguyên mà là mảng chứa các nhóm User được chọn. Chọn Add Option và nhập các thông tin:

  • Option ID: ghChuky_cfgroup
  • Add-on: Chọn Add on của bạn
  • Title: Chọn nhóm user cần kiểm tra khi ký
  • Edit Format: Php Callback
  • Format Parameters:
    <?php GhChuky_Option_Group::renderOption
  • Data Type: Array

Các tham số khác để nguyên, Save lại.

Ở tùy chọn này thì kiểu dữ liệu bạn phải xử lý (chọn Php Callback), và đoạn code xử lý nằm trong lớp/hàm  
GhChuky_Option_Group::renderOption 
tương ứng nằm ở file:
GhChuky/Option/Group.php

Giờ ta phải viết code cho phần đó, bạn mở thư mục GhChuky tạo thư mục Option, vào Option tạo file Group.php, rồi đưa đoạn mã php sau vào:

<?php
class GhChuky_Option_Group
    {

        public static function renderOption(XenForo_View $view, $fieldPrefix, array $preparedOption, $canEdit)
        {

            $preparedOption['formatParams'] = XenForo_Model::create('GhChuKy_Model_GetUserGroups')->getUserGroupOptions(
            $preparedOption['option_value']
            );

            return XenForo_ViewAdmin_Helper_Option::renderOptionTemplateInternal(
            'option_list_option_checkbox',
            $view, $fieldPrefix, $preparedOption, $canEdit
            );

        }

    }

Trong đoạn mã trên có truy cập đến database để lấy dữ liệu, đó là đoạn:

XenForo_Model::create('GhChuKy_Model_GetUserGroups')->getUserGroupOptions($preparedOption['option_value']);

Nó chỉ ra truy cập dữ liệu qua Model: 

GhChuKy_Model_GetUserGroups

Giờ ta phải tạo ra Model đó:

Mở lại thư mục GhChuky, tạo ra thư mục Model, trong Model tạo file: GetUserGroups.php

Sau đó đưa nội dung vào file đó như sau:

<?php
class GhChuky_Model_GetUserGroups extends XenForo_Model
{  
        public function getUserGroupOptions($selectedGroupIds)
        {

            $userGroups = array();
            foreach ($this->getAppropriateUserGroups() AS $userGroup)
            {
                $userGroups[] = array(
                'label' => $userGroup['title'],
                'value' => $userGroup['user_group_id'],
                'selected' => in_array($userGroup['user_group_id'], $selectedGroupIds)
                );
            }

            return $userGroups;

        }

        public function getAppropriateUserGroups()
        {
            return $this->_getDb()->fetchAll('
            SELECT user_group_id, title
            FROM xf_user_group
            WHERE user_group_id = 2 OR user_group_id > 4
            ORDER BY user_group_id
            ');

        }

    }

Đến đây bạn đã có bảng tùy chọn các tham số cho Addon rồi, bạn kiểm tra thử trong AdminCP xem. Tuy nhiên dữ liệu đó chưa được hàm actionSignature() sử dụng.

Giờ thêm đoạn code có sử lý lấy Options, bạn lưu ý để lấy tất cả các Option trong XF bạn dùng lệnh:

$options = XenForo_Application::get('options');

Có $options rồi bạn cần truy cập vào biến nào thì rất đơn giản, bằng cú pháp

$options->id-của-option //Ví dụ ghChuky_group, ghchuky_msgcount

Vậy ta có đoạn mã có xét đến option khi ký như sau

<?php
class GhChuky_ControllerPublic_GhChuky extends XFCP_GhChuky_ControllerPublic_GhChuky{

    public function actionSignature()
    {
        
        if (!XenForo_Visitor::getInstance()->canEditSignature())
        {
            return $this->responseNoPermission();
        }
        
        $sigPerms = array();
        $visitor = XenForo_Visitor::getInstance();
        $options = XenForo_Application::get('options');
     
        if ($visitor['message_count'] < $options->ghchuky_msgcount AND
        (!$visitor['is_moderator'] AND !$visitor['is_admin']))
        {
            $applytogroups = $options->ghChuky_group;
            if (empty($applytogroups))
            {
                $applytogroups = array(2);  // default it to Registered group
            }

            $belongstogroups = $visitor['user_group_id'];
            if (!empty($visitor['secondary_group_ids']))
            {
                 $belongstogroups .= ','.$visitor['secondary_group_ids'];
            }
            $groupcheck = explode(',',$belongstogroups);
            unset($belongstogroups);
            $sigcheck = true;
            foreach ($groupcheck AS $groupId)
            {
                if (in_array($groupId, $applytogroups))
                {
                    $sigcheck = false;
                    break;
                }

            }

           if (!$sigcheck)
           {
              return $this->responseError('Bạn chưa đủ bài viết để ký;)');
           }
    
        } 

        $sigPerms['basic'] = $visitor->hasPermission('signature', 'basicText');
        $sigPerms['extended'] = $visitor->hasPermission('signature', 'extendedText');
        $sigPerms['align'] = $visitor->hasPermission('signature', 'align');
        $sigPerms['indent'] = $visitor->hasPermission('signature', 'align');
        $sigPerms['smilies'] =  $visitor->hasPermission('signature', 'maxSmilies') != 0;
        $sigPerms['link'] = $visitor->hasPermission('signature', 'link') && $visitor->hasPermission('signature', 'maxLinks');
        $sigPerms['image'] = $visitor->hasPermission('signature', 'image') && $visitor->hasPermission('signature', 'maxImages');
        $sigPerms['media'] = $visitor->hasPermission('signature', 'media');
        $sigPerms['block'] = $visitor->hasPermission('signature', 'block');
        $sigPerms['list'] = $visitor->hasPermission('signature', 'list');

        return $this->_getWrapper(
            'account', 'signature',
            $this->responseView(
                'XenForo_ViewPublic_Account_Signature',
                'account_signature',
                array('sigPerms' => $sigPerms)
            )
        );

    }

}

Giờ bạn đã có một Addon hoàn chỉnh, phiên bản 2.0 ;)

Bạn có thể tải Addon V2 này về tham khảo hoặc cài đặt: addon-ghchuky2.0.zip

Trên đây là các bước để tạo Addon cơ bản cho Xenforo, chúc thành công!