Hướng dẫn phát triển add-on cho Xenforo

Nội dung trong bài viết được thay đổi một vài phần nhằm giúp các bạn dễ hiểu hơn khi tạo môt add-on cho XenForo.

PHẦN 1
Hướng dẫn này sẽ từng bước chỉ ra cách tạo một ứng dụng (add-on) cho Xenforo.

Add-on của bài viết này được tạo ra nhằm hạn chế thành viên sử dụng chữ ký khi chưa có đủ post tối thiểu. Để thực hiện điều này, chúng ta cần tạo ra Listener, Admin Option và những file PHP cần thiết.

Tác giả không sử dụng screenshot trong bài viết này nhằm giúp người đọc hiểu được mô hình MVC của Xenforo và cách thức tạo nên một add-on. Từng bước đều có giải thích chi tiết.

Trước tiên, để có thể bắt tay tạo ra một Add-on, chúng ta phải bật debug và development mode trong AdminCP.

Chú ý: Bạn không thấy mục Development là do chưa bật debug thôi, mở file config.php ở trong thư mục library thêm dòng sau vào là sẽ thấy :

$config['debug'] = true;

Để làm điều đó, bạn hãy tìm đến thư mục library trong thư mục xenforo của bạn. Bạn sẽ thấy file config.php, nếu bạn không chắc chắn về việc chỉnh sửa file, hãy backup lại file config.php này.

Bạn có thể mở file config.php và thêm và dưới cùng :

$config['debug'] = true;

Trong một số trường hợp, bạn sẽ cần thêm

// $config['enableListeners'] = false;

Tuy nhiên nó cũng chưa cần thiết lắm.

Sau khi sửa xong, hãy save nó lại.

Tạo Add-on trong AdminCP

Đăng nhập vào AdminCP với tài khoản admin của bạn, bây giờ bạn có thể thấy Development trên navbar của AdminCP và click vô. Ở Development có rất nhiều thứ, nhưng ở Tut này chúng ta chỉ quan tâm tới Add-on và Listener. Hãy click vào Create Add-on, những thứ cần điền ở đây.

Version ID dùng để theo dõi những thay đổi trong quá trình sửa đổi Add-on, mỗi lần thay đổi thì tăng lên 1.
Những ô còn lại chúng ta tạm thời không cần tới. Click Save Add-on.

Với mục đích hạn chế sử dụng chữ ký, chúng ta cần phải xác định vị trí mà thành viên có thể thay đổi chữ ký, vậy nên chúng ta cần phải sử dụng Listener để lắng nghe các class được gọi ra, và nó được điều khiển bởi Controller. Có 4 thư mục Controller gồm: ControllerAdmin, ControllerHelper, ControllerPublic và ControllerResponse. Việc thay đổi chữ ký không thể thực hiện trong ControllerAdmin, ControllerHelper và ControllerRespone, vì vậy chỉ còn lại ControllerPublic là có thể. Vì thay đổi chữ ký là một phần của account vì thế nên chúng ta hãy quan tâm tới Account.php. Mở file Account.php và tìm “signature”, chúng ta sẽ thấy ngay function đầu tiên tìm được.

/**
* Signature form
*
* @return XenForo_ControllerResponse_View
*/
public function actionSignature()
{
if (!XenForo_Visitor::getInstance()->canEditSignature())
{
return $this->responseNoPermission();
}
return $this->_getWrapper(
'account', 'signature',
$this->responseView(
'XenForo_ViewPublic_Account_Signature',
'account_signature'
)
);
}

Đây là function mà chúng ta có thể ghi đè (override) được.

Giờ chúng ta phải lắng nghe class có chứa và gọi function trên (XenForo_ControllerPublic_Account).
Xenforo có cung cấp khá nhiều Listener mà ta có thể chọn. Hãy chọn Development -> chọn Code Event Listener và chọn Create new code event listener.

Ở ô dropdown đầu tiên, chúng ta có thể chọn Event nào được lắng nghe. Khi chúng ta muốn lắng nghe class từ controller được nạp, hãy chọn Load_Class_Controller.

Listener của Load_Class_Controller khá là khó sử dụng, nhưng nó khá mạnh mẽ và cung cấp rất nhiều Listener linh hoạt nhất. Khi bạn chọn một Listener, sẽ có thông báo giải thích về class phải được khởi tạo trong file PHP:

class My_Class_Name extends XFCP_My_Class_Name
{
// functionality to extend/override
}

Đó là sự thật, nhưng nó không thể được tải trực tiếp. Tải class này trực tiếp sẽ dẫn đến AutoLoader đưa ra lỗi:

Lỗi này lý giải rằng, class mà bạn khởi tạo phải được nạp trước khi nó được xử lý. Nhưng lại có câu hỏi được đặt ra, đó là làm thế nào để nạp nó và nạp ở đâu ? Đây chính là mục đích của đối số mảng $extend .

PHẦN 2
Bắt đầu phần 2, chúng ta sẽ tạo một số thư mục theo cấu trúc định sẵn, hãy mở thư mục library, tạo một thư mục LimitSig, cách đặt tên thư mục như nào là tùy bạn, nhưng nên đặt tên sao cho dễ kiểm soát và phù hợp với mục đích của Add-on. Hãy lưu ý, chữ L và chữ S được viết hoa, đây là định dạng tiêu chuẩn theo tên của thư mục XenForo.

Mở thư mục LimitSig, và tạo một thư mục mới tên là Listener, thư mục này sẽ là nơi lưu trữ những listener. Vào trong thư mục Listener, hãy tạo 1 file có tên LoadClassController.php. Cấu trúc thư mục và tên file mà chúng ta sử dụng sẽ giúp chúng ta dễ dàng hơn trong việc xác định vị trí và sửa đổi trong tương lai.

Mở file LoadClassController.php và thêm vào đoạn dưới đây:

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

Save file này lại.

Nếu bạn để ý thì sẽ thấy tên class sẽ phản ánh cấu trúc thư mục, điều này tương đối quan trọng. function sẽ có 2 đối số đầu vào: $class và $extend$class sẽ chứa class mà chúng ta sẽ test, còn $extend là mảng mà chúng ta sẽ thêm vào $classmà có chứa XenForo_ControllerPublic_Account. Sử dụng mảng sẽ cho phép các Add-on khác sử dụng Listener mà không cần phải can thiệp vào.

Bây giờ, chúng ta có thể add Class và Method trong Execute Callback:

Chắc chắn rằng Enable callback execution được chọn

Chọn Limit signature for new Members ở dropdown Add-on

Save lại. Bây giờ Listener đã được lưu thành công.

class ở file LoadClassController.php sẽ lắng nghe XenForo_ControllerPublic_Account. Khi class được nạp, $extend sẽ cư ngụ dưới tên LimitSig_ControllerPublic_LimitSig. Bây giờ chúng ta phải tạo file và class này. Nhìn tên class, chúng ta sẽ thấy được cấu trúc tạo thư mục và file:

Hãy tạo thư mục ControllerPublic bên trong thư mục LimitSig, và sau đó là file LimitSig.php, bên trong LimitSig.php bạn hãy thêm vào đoạn dưới:

<?php
class LimitSig_ControllerPublic_LimitSig extends XFCP_LimitSig_ControllerPublic_LimitSig
{
public function actionSignature()
{
}
}

Bạn hãy để ý tới tiền tố XFCP_ được sử dụng để tham chiếu tới listener. Vì chúng ta không thể mở rộng class không tôn tại, hãy nạp nó vào $extend để chứng thực rồi mới có thể mở rộng class của chúng ta.

Hãy chú ý, hàm actionSignature() mà chúng ta sử dụng là để ghi đè lên hàm có sẵn trong Account.php. Bên trong file này, chúng ta sẽ sử dụng code để kiểm tra số lượng post của thành viên. Tuy nhiên, chúng ta nên tạm thời để trống và tạo Option trong AdminCP trước.
Nếu muốn, bạn có thể tạm thời tắt Add-on này đi cho đến khi chúng ta thêm code xử lý.

PHẦN 3
Ở phần này, chúng ta sẽ tạo Option cho Add-on trong AdminCP. Hãy vào AdminCP -> Option, click vào + Add Option Group, điền thông số như dưới đây:

Click Save Option Group.

Vậy là cơ bản bạn đã tạo ra 1 nhóm mới, và bây giờ là lúc thêm Option vào nhóm này. Option đầu tiên là để xác định số post nhỏ nhất mà thành viên phải có để có thể tạo được chữ ký. Option thứ 2 là để gán số post nhỏ nhất cho những nhóm nào. Việc thêm Option nhóm là để cho phép chúng ta chọn những nhóm bắt buộc phải kiểm tra số post và những nhóm không cần kiểm tra. Lấy ví dụ như: Thành viên mới thì bắt buộc phải có lượng post tối thiểu mới được tạo chữ ký, trong khi Admin thì không cần đạt đủ số post nhưng vẫn có thể tạo chữ ký.

Click Add Option

Ở đây, bạn sẽ có một số textbox, checkbox và dropdown mà bạn có thể sử dụng. Option đầu tiên là Option ID, đây chính là ID của Option mà ta sẽ test ở LimitSig.php. Hãy đặt tên sao cho dễ nhớ và đồng bộ với Add-on. Trong ví dụ này, chúng ta sẽ lấy tên là : sigmessageCount.

Các Option còn lại thì điền như sau :

Edit Format.Từ dropdown, chọn loại option thích hợp: textbox, spinbox, On/Off Check box, Radio Button, Select Menu, Check Box, Named Template hoặc PHP Callback. Vì chúng ta sử dụng số để giới hạn, vì thế ta chọn Spin Box. Tuy nhiên, một số trường hợp có thể dùng textbox cũng được.

Format Parameters.Bạn có thể set giới hạn và hành vi một số loại Option. Vì chúng ta sử dụng Spin Box, chúng ta có thể thêm Min, Max và Step. Bất kỳ số nào nhỏ hơn Min sẽ được trả về mặc định Min, và tương tự với Max. Mỗi option đều viết trên một dòng. Step ở đây theo đúng nghĩa, nó dùng để tăng hay giảm số lượng nhất định khi ấn “+” hay “-“. Nếu muốn tăng mặc định là 1, bạn có thể bỏ dòng Step=x.

Data Type: Đây là loại biến mà bạn muốn gán. Chọn Unsigned Integer từ dropdown. Chúng ta không muốn giá trị của biến là một số âm hay bất kỳ số nào nhỏ hơn 1 sẽ đều trả về 1, và chúng ta muốn có thể sử dụng cả số 0.

Default Value.Đây là giá trị mặc định của Option khi Add-on được import vào. Nếu muốn mặc định giới hạn post của thành viên là 5 bài, chúng ta sẽ để giá trị mặc định là 5.

Array Sub Options. vì chúng ta không sử dụng tới mảng để lưu biến, vì thế chúng ta để trống ô này.

Validation Callback.Để trống nốt. Ô này được dùng khi bạn muốn kiểm tra lựa chọn của Admin. Ví dụ: nếu trong 1 Forum mà Admin chọn thì phải chính xác là Form chứ không phải là Category hay là Page.

Display in Groups.Đây là danh sách các Option Group mà bạn muốn Option này hiện. Mặc định là Add-on được chọn ở dropdown đầu tiên. Để nguyên theo mặc định.

Include this Option in Backups. Default checked. Checked.

Click Save Option. Bây giờ bạn đã có Option đầu tiên trong Signature Option Group

Một lần nữa Add Option.

Edit Format: PHP Callback. Sử dụng PHP Callback để tạo ra danh sách nhóm thành viên, bao gồm cả nhóm mà Admin đã tạo.

Format Parameters.Vì sử dụng PHP Callback, chúng ta phải trỏ Option tới Class và Method đã sử dụng: LimitSig_Option_Group::renderOption

Data Type: Array. Vì có thể chọn nhiều nhóm, vậy nên dùng mảng là điều cần thiết.

Default Value: a:1:{i:0;s:1:”2″;}. Giá trị mặc định sẽ gán cho nhóm Registered. Về cách thay đổi giá trị này, chúng ta sẽ bàn tới sau khi mà option hoạt động theo ý muốn

Array Sub-Options: * (Chúng ta sử dụng * ở đây là vì chúng ta không cần lưu trữ thông tin từ khóa chỉ định của mảng, như: width, height, user_id, v.v…)

Validation Callback: default.Vì chúng ta điều khiển những nhóm nào mà Admin có thể chọn, chúng ta biết rằng nó hợp lệ.

Trước khi Save Option, chúng ta cần phải tạo PHP Callback Class và Method để xuất ra danh sách nhóm thành viên.

PHẦN 4
Giờ chúng ta sẽ tạo Callback để xuất ra các checkbox cho option, có tên là LimitSig_Option_Group. Vào thư mục LimitSig -> thư mục Option -> tạo file Group.php, thêm đoạn dưới đây vào :

<?php

    class LimitSig_Option_Group
    {

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

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

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

        }

    }

Save lại.

Class này sẽ truyền danh sách các nhóm người dùng được tạo ra bởi LimitSig_Model_GetUserGroups để xuất ra các checkbox bởi Admin Helper. Để xem tất cả các render option phù hợp, hãy bỏ chút thời gian để xem file Admin Helper Option.

Vẫn theo format cũ, từ thư mục LigmitSig, tạo thư mục Model, ở trong tạo file GetUserGroups.php, thêm đoạn phía dưới:

<?php

    class LimitSig_Model_GetUserGroups extends XenForo_Model
    {

    // returns a list user groups with the exception of Administrative, Moderating, and Unregistered

        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
            ');

        }

    }

Save lại.

File này sẽ trả về danh sách các nhóm người dùng mà sẽ xuất thành các checkbox, ngoại trừ Unregistered, Administrative và Moderating. Những nhóm người dùng bổ sung, hoặc tự tạo mới đều có trong danh sách.

Để xem các checkbox được tạo ra hay chưa: vào AdminCP -> Options -> Signature Options. Bạn sẽ thấy Registered User (mặc đình là checked) và các nhóm khác mà bạn tạo ra đều xuất hiện trong danh sách.

Cách set giá trị mặc định cho checkbox:

Nếu gọi lại, chúng ta sẽ đặt a:1:{i:0;s:1:”2″;} là giá trị mặc định, khi chúng ta tạo option Apply to Group. Khi mới khởi tạo option có nhiều lựa chọn, cách dễ nhất là để mặc định là blank. Tạo một Callback, rồi option, chọn những cái nào để mặc định, rồi Save.

Giờ hãy vào phpMyAdmin, mở Database Xenforo, bảng xf_option. có một vài cột được lưu dưới dạng BLOB, điển hình là cột default_value. Để xem nội dung của cột default_value, chúng ta sẽ export bảng này ra. Click tab Export, ở phía bên phải dưới, có tùy chọn Use hexadecimal for binary field, hãy bỏ chọn nó, rồi click Go để lưu lại.

Mở file vừa lưu về ra bằng bất cứ trình edit nàom, có thể là Notepad.

('siglimitGroups', 'a:1:{i:0;s:1:"5";}', 'a:1:{i:0;s:1:"2";}', 'callback', 'LimitSig_Option_Group::renderOption', 'array', '*', 1, '', '', 'limitSigs');

Giá trị mặc định luôn nằm ở cột thứ 3, vì vậy hãy copy đoạn a:1:{i:0;s:1:”2″;} .

PHẦN 5
Khi tạo xong options trong AdminCP, chúng ta cần có code để kiểm tra số post và nhóm thành viên để kiểm tra xem họ có quyền sửa chữ ký hay không.
Mở : LimitSig/ ControllerPublic/ LimitSig.php

Thay thế toàn bộ nội dung bên trong bằng :

public function actionSignature()
    {

        if (!XenForo_Visitor::getInstance()->canEditSignature())
        {

            return $this->responseNoPermission();
        }

        else
        {
                $visitor = XenForo_Visitor::getInstance();

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

                if ($visitor['message_count'] < $options->sigmessageCount AND
                   (!$visitor['is_moderator'] AND !$visitor['is_admin']))
                {

                            $applytogroups = $options->siglimitGroups;

                            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->responseNoPermission();
                            }

                }

        }

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

    }

Giải thích một chút về code. Câu lệnh If đầu tiên để kiểm tra quyền của thành viên, nếu không thì hiển thị thông báo. Tức là nếu đang là khách, thì khi vào phần sửa chữ ký, sẽ có thông báo lỗi được hiển thị.

Còn nếu là thành viên, chúng ta cần phải kiểm tra số post và quyền hạn. Chúng ta sẽ đẩy thông tin của thành viên ra bằng câu lệnh:

$visitor = XenForo_Visitor::getInstance();

Giờ chúng ta cần thiết lập của Signature Option:

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

Giờ chúng ta có thể so sánh số post của thành viên, và xem thành viên có là Admin hay Mod không. Nếu thành viên là Admin, Mod hoặc số post lớn hơn so với thiết lập, thì bỏ qua kiểm tra nhóm.

Ngược lại, chúng ta cần phải kiểm tra nhóm thành viên mà Admin thiết lập kiểm tra.

$applytogroups = $options->siglimitGroups;

Nếu $applytogroups  trống, chúng ta sẽ mặc định nhóm kiểm tra là Registered User. Vì thành viên có thể tham gia nhiều nhóm, tức là có nhóm chính và nhóm phụ, chúng ta sẽ phải ghép lại thành một mảng. Vòng lặp foreach, dùng để kiểm tra từng phần tử trong mảng, chúng ta sẽ bỏ qua kết quả dương thứ nhất, và hiển thị ra lỗi No Permission, hoặc không thì hiển thị bảng chỉnh sửa chữ ký.

Cách Export Add-on:

Ở phần dropdown Controls, chọn Export. XML sẽ bao gồm Listener, các Option, nếu có các template thì cũng sẽ được bổ sung.

Vậy là Tut Hướng dẫn viết Add-on cho Xenforo đã kết thúc, chắc hẳn các bạn sẽ hiểu được phần nào quá trình và cách thức tạo Add-on.

Bài viết được trích dẫn từ
http://vxf.vn/threads/huong-dan-phat-trien-addon-cho-xenforo.18/
Dịch từ bản gốc :
http://xenforo.com/community/threads/creating-an-addon.5416/

Leave a Reply

Your email address will not be published. Required fields are marked *