Користувальницькькі налаштування

Налаштування сайту


Сайдбар

Розділи

Загальний опис
Історія змін
Рекомендації щодо оновлення
Плани на майбутнє
Відомі проблеми
Онлайн демо
Люди
Трохи про безпеку

FAQ



Редагувати сайдбар

development

Короткий посібник із розробки модулів для Ubilling

Писати додаткові модулі для Ubilling дуже просто, розгляньмо процес написання найпростішого модуля на прикладі модуля, що показує всіх користувачів з їхніми ПІБ та адресами у вигляді гарної сортувальної таблички.

Типовий модуль Ubilling розміщується в окремому підкаталозі /modules/general/ і складається з двох файлів: index.php і module.php. Перший із них є власне модулем із його виконуваним кодом, другий же - описом модуля для вбудованого диспатчера. Давайте припустимо, що наш модуль називатиметься samplemod і таким чином складатиметься з двох файлів:


Давайте детально розберемо що-ж знаходиться в цих двох містичних файликах.

module.php
  <?php
  $this->registerModule($module, 'main', 'Sample module', 'Sample developer', array('SAMPLE' => __('right for access sample module')));

Містить у собі стандартний набір, який описує те, що модуль має клас main (тобто може розміщуватися в центральному блоці контенту за замовчуванням), зветься Sample module, написаний розробником на ім'я Sample developer і під час свого довантаження породжує право SAMPLE, за яким згодом ми розмежовуватимемо доступ до цього модуля. Зверніть увагу на конструкцію

__('Рядок англійською')

використану в цьому прикладі в ролі опису права на модуль. Функція повертатиме локалізований рядок відносно поточної мови, якщо він знайдений у словниковому файлі. Власне локалізація в Ubilling є подібною до gettext.
Все, з файлом опису модуля розібралися, поїхали далі.


index.php
<?php
  // перевіряємо чи має користувач права на користування цим модулем
  if (cfr('SAMPLE')) {
 
    //робимо запит до БД з метою отримати логіни всіх користувачів
    $query="SELECT `login`,`IP` from `users`";
    $alllogins=simple_queryall($query);
 
    //отримуємо масиви всіх П.І.Б. користувачів та їхніх адрес
    $allrealnames=zb_UserGetAllRealnames();
    $alladdress=zb_AddressGetFulladdresslist();
 
    //перевіряємо, чи є взагалі у нас користувачі
    if (!empty ($alllogins)) {
 
            //Збираємо заголовок таблички для виведення
            $tablecells=wf_TableCell(__('Login'));
            $tablecells.=wf_TableCell(__('IP'));
            $tablecells.=wf_TableCell(__('Real Name'));
            $tablecells.=wf_TableCell(__('Address'));
            $tablerows=wf_TableRow($tablecells, 'row1');
 
        // Перебираємо всіх користувачів
        foreach ($alllogins as $io=>$eachlogin) {
            $userlogin=$eachlogin['login'];
            $userip=$eachlogin['IP'];
 
            //Збираючи для кожного рядка таблички
            $tablecells=wf_TableCell($userlogin);
            $tablecells.=wf_TableCell($userip);
            $tablecells.=wf_TableCell(@$allrealnames[$userlogin]);
            $tablecells.=wf_TableCell(@$alladdress[ $userlogin]);
            $tablerows.=wf_TableRow($tablecells, 'row3');
        }
 
        // оголошуємо як результат табличку з попередньо зібраними рядками
        // а також шириною в 100%, бордюром в 0 і класом sotrable
        $result=wf_TableBody($tablerows, '100%', '0', 'sortable');
 
    } else {
        //якщо немає натякаємо що їх немає
        $result=__('No users found');
    }
 
    // виводимо наш результат за допомогою функції show_window
    show_window(__('Sample module'), $result);
 
 
  } else {
      // якщо ні - вивалюємо на нього помилку про відмову в доступі
      show_error(__('You cant control this module'));
  }

Доступ до нашого модуля ми можемо отримати за допомогою посилання ?module=samplemod, в результаті чого ми повинні побачити приблизно таке:

Як бачите, замість рядків Real Name і Address у нас автоматично підставилися їхні мовно-залежні заміни зі словника поточної локалізації. Не перекладеним залишився один рядок Sample module, про який рушій локалізації поки що нічого не знає. Давайте перекладемо його скажімо російською мовою для початку.\
Зробити це досить просто - потрібно створити файл /languages/ukrainian/samplemod.php такого змісту:

samplemod.php
<?php
$lang['def']['Sample module'] = 'Модуль для прикладу';
$lang['def']['Yet another string'] = 'Ще якийсь рядок';

Після чого ми побачимо як рядок локалізувався сам по собі в нашому модулі:


З нестандартних речей, чужих чистому PHP, ми використовували тільки функції бібліотеки api.astral для збирання таблиць за допомогою wf_, що не є обов'язковою, просто виглядає красивіше та читабельніше, а також результат крізь show_window($title,$data) замість print(), що вже є обов'язковою для роботи шаблонізатора фреймворка.

А що робити, якщо нашому модулю потрібна якась бібліотека/клас потрібна йому одному? Варіантів є кілька. Перший з них менш красивий, але більш портабельний - вставити її прямо всередину нашого модуля в modules/general/samplemod/index.php. Другий - просто покласти цю бібліотеку в директорію modules/engine/. У цьому разі вона буде довантажена до виконання нашого модуля. Хорошим тоном у цьому випадку буде переконатися, що під час свого завантаження вона не буде виробляти якогось виводу, і друге - постарайтеся уникати створення великих об'єктів у цій бібліотеці, щоб уникнути деградації продуктивності загалом. Що мається на увазі під цим? Наведемо на прикладі бібліотеки, яка описує якийсь клас SampleClass і знаходиться в modules/engine/sampleClass.php

sampleClass.php
<?php
 
class SampleClass {
 
  protected $data=array();
 
  public function __construct() {
    $this->loadData();
  }
 
  protected function loadData() {
    $this->data=......
  }
 
}
 
$sampleObject=new SampleClass(); // ось цього тут бути не повинно, місце йому в modules/general/samplemod/index.php
 
?>

Також чудовим (і рекомендованим!) способом може бути розміщення вашої бібліотеки в api/libs/, звідки її може підхопити автозавантажувач, якщо ім'я класу створюваного об'єкта відповідає імені бібліотеки з префіксом “api.” у лаверкейсі. Для прикладу вище це має бути файл api/libs/api.sampleclass.php. Під час створення об'єкта $sampleObject=new SampleClass(); цю бібліотеку буде автоматично завантажено, і вам взагалі нічого не потрібно для цього робити.

Розташування модуля на панелі задач

А як додаються модулі на панель завдань? Ну там з іконками, правами та опціями? А все так само дуже просто - розкладанням потрібних файликів у потрібні місця. Починаючи з релізу 0.8.0 цими місцями є директорія config/taskbar.d/, а точніше її підкаталоги. Припустимо, наш тестовий модуль є з нашої точки зору звітом. Також ми хочемо, щоб вмикався він за допомогою необов'язкової опції alter.ini на ім'я SAMPLE_ENABLED. Разом кладемо файлик sample.ini в директорію config/taskbar.d/reports/

sample.ini
; Ідентифікатор модуля. Повинен бути як мінімум унікальним.
ID="samplemod"
; Підпис іконки модуля - буде автоматично локалізовано поточною локаллю.
NAME="Sample module"
; URL нашого модуля. Не повірите - буде клікабельним :)
URL="?module=samplemod"
; Іконка модуля. Спочатку намагається знайтися в директорії taskbar поточного скіна, якщо не існує - у глобальному skins/taskbar.
ICON="goat.gif"
; Право, яке вимагає модуль. Ну як мінімум право, яке потрібне для показу іконки.
NEED_RIGHT="SAMPLE"
; Опція конфіга alter.ini необхідна для показу іконки таскбару.
NEED_OPTION="SAMPLE_ENABLED"
; Цей параметр сигналізує, що опція є необов'язковою. 
; Якщо видалити цей параметр - панель завдань буде кричати про відсутню опцію.
UNIMPORTANT=1
; Тип елемента. У нашому випадку це icon - типова іконка з підписом. Є ще widget але про це пізніше.
TYPE="icon"
; Ця необов'язкова опція описує те буде відкриватись посилання на елемент. 
; Може бути відсутньою чи порожньою або приймати значення _blank, _self, _parent, _top чи ім'я iframe. 
; детальніше тут: https://www.w3schools.com/tags/att_a_target.asp
LINK_TARGET=

та отримуємо результат очікуваний результат

А що ж із віджетами, і як вони взагалі виглядають? А ось якось так так.

Приклад використання dataTable

   // jQuery dataTable construction and rendering
    $myUrl = '?module=testing';
    $callbackRoute = 'ajaxlist';
    $columns = array('Якась колонка', 'Друга колонка');
    $dataTable = wf_JqDtLoader($columns, $myUrl . '&' . $callbackRoute . '=true', false, __('Data'), 50);
    show_window(__('Title'), $dataTable);
 
    // JSON dataTable data output on some callback route
    if (ubRouting::checkGet($callbackRoute)) {
        $json = new wf_JqDtHelper();
        $json->addRow(array('якісь дані', 'інші дані'));
        $json->addRow(array('це в першій колонці', 'також дані'));
        $json->getJson();
    }

результат

Розташування модулю як плагіну профілю користувача

Формат plugins.ini дуже близький до формату опису елементу панелі задач. Тільки імена опцій в лаверкейсі.

plugins.ini
[унікальний ідентифікатор модуля]
name = "Ім'я модулю"
icon = "ім'я файлу іконки модулю"
need_right=Право яке необхідне модулю
need_option=Опція яка необхідна
;Наступна опція не є обов`язковою. Просто вказує те де буде відкрито посилання.
;детальніше тут: https://www.w3schools.com/tags/att_a_target.asp
;link_target=_self

також модуль може бути описаним у оверлеї “чорної магії” в bmagic.ini в тому ж форматі.

development.txt · Востаннє змінено: 2024/12/23 11:48 повз nightfly