====== Короткий посібник із розробки модулів для Ubilling ======
Писати додаткові модулі для Ubilling дуже просто, розгляньмо процес написання найпростішого модуля на прикладі модуля, що показує всіх користувачів з їхніми ПІБ та адресами у вигляді гарної сортувальної таблички.
Типовий модуль Ubilling розміщується в окремому підкаталозі **/modules/general/** і складається з двох файлів: **index.php** і **module.php**. Перший із них є власне модулем із його виконуваним кодом, другий же - описом модуля для вбудованого диспатчера. Давайте припустимо, що наш модуль називатиметься samplemod і таким чином складатиметься з двох файлів:\\
\\
{{:samplemod.png?|}}
\\
Давайте детально розберемо що-ж знаходиться в цих двох містичних файликах.\\
registerModule($module, 'main', 'Sample module', 'Sample developer', array('SAMPLE' => __('right for access sample module')));
Містить у собі стандартний набір, який описує те, що модуль має клас **main** (тобто може розміщуватися в центральному блоці контенту за замовчуванням), зветься **Sample module**, написаний розробником на ім'я **Sample developer** і під час свого довантаження породжує право **SAMPLE**, за яким згодом ми розмежовуватимемо доступ до цього модуля. Зверніть увагу на конструкцію __('Рядок англійською')
використану в цьому прикладі в ролі опису права на модуль. Функція повертатиме локалізований рядок відносно поточної мови, якщо він знайдений у словниковому файлі. Власне локалізація в Ubilling є подібною до gettext.\\
Все, з файлом опису модуля розібралися, поїхали далі.\\
\\
\\
$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**, в результаті чого ми повинні побачити приблизно таке:\\
{{:samplemod2.png?|}}
Як бачите, замість рядків **Real Name** і **Address** у нас автоматично підставилися їхні мовно-залежні заміни зі словника поточної локалізації. Не перекладеним залишився один рядок **Sample module**, про який рушій локалізації поки що нічого не знає. Давайте перекладемо його скажімо російською мовою для початку.\\\
Зробити це досить просто - потрібно створити файл **/languages/ukrainian/samplemod.php** такого змісту:
Після чого ми побачимо як рядок локалізувався сам по собі в нашому модулі:\\
{{:samplemod3.png?|}}
\\
З нестандартних речей, чужих чистому PHP, ми використовували тільки функції бібліотеки** api.astral** для збирання таблиць за допомогою **wf_**, що не є обов'язковою, просто виглядає красивіше та читабельніше, а також результат крізь **show_window($title,$data)** замість **print()**, що вже є обов'язковою для роботи шаблонізатора фреймворка.\\
А що робити, якщо нашому модулю потрібна якась бібліотека/клас потрібна йому одному? Варіантів є кілька. Перший з них менш красивий, але більш портабельний - вставити її прямо всередину нашого модуля в **modules/general/samplemod/index.php**. Другий - просто покласти цю бібліотеку в директорію **modules/engine/**. У цьому разі вона буде довантажена до виконання нашого модуля. Хорошим тоном у цьому випадку буде переконатися, що під час свого завантаження вона не буде виробляти якогось виводу, і друге - постарайтеся уникати створення великих об'єктів у цій бібліотеці, щоб уникнути деградації продуктивності загалом. Що мається на увазі під цим? Наведемо на прикладі бібліотеки, яка описує якийсь клас SampleClass і знаходиться в **modules/engine/sampleClass.php**
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/**, а точніше її підкаталоги. Припустимо, наш тестовий модуль є з нашої точки зору звітом. Також ми хочемо, щоб вмикався він за допомогою необов'язкової опції [[alteriniconf|alter.ini]] на ім'я SAMPLE_ENABLED. Разом кладемо файлик sample.ini в директорію **config/taskbar.d/reports/**
; Ідентифікатор модуля. Повинен бути як мінімум унікальним.
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=
та отримуємо результат очікуваний результат
{{:undefined:samplemod4.png|}}
А що ж із віджетами, і як вони взагалі виглядають? А ось якось так [[taskbarwidgets|так]].
====== Приклад використання 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();
}
результат
{{:jqdt.png|}}
====== Розташування модулю як плагіну профілю користувача ======
Формат plugins.ini дуже близький до формату опису елементу панелі задач. Тільки імена опцій в лаверкейсі.
[унікальний ідентифікатор модуля]
name = "Ім'я модулю"
icon = "ім'я файлу іконки модулю"
need_right=Право яке необхідне модулю
need_option=Опція яка необхідна
;Наступна опція не є обов`язковою. Просто вказує те де буде відкрито посилання.
;детальніше тут: https://www.w3schools.com/tags/att_a_target.asp
;link_target=_self
також модуль може бути описаним у оверлеї "чорної магії" в bmagic.ini в тому ж форматі.