====== Короткий посібник із розроблення модулів для 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/russian/samplemod.php** такого змісту:
Після чого ми побачимо як рядок локалізувався сам по собі в нашому модулі:\\
{{:samplemod3.png?|}}
\\
З нестандартних речей, чужих чистому PHP, ми використовували тільки функції бібліотеки** api.astral** для збирання таблиць за допомогою **wf_**, що не є об'язковою, просто виглядає красивіше та читабельніше, а також висновок крізь **show_window($title,$data)** замість **print()**, що вже є об'язковою для роботи шаблонізатора фреймворка.\\
А що робити, якщо нашому модулю потрібна якась бібліотека/клас потрібна йому одному? Варіантів є кілька. Перший з них менш красивий, але більш портабельний - вставити її прямо всередину нашого модуля в **modules/general/smaplemod/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(); цю бібліотеку буде автоматично завантажено, і вам взагалі нічого не потрібно для цього робити. Ця механіка з'явилася починаючи з релізу Ubilling 0.8.6 Chainsaw.
А як додаються модулі на панель завдань? Ну там з іконками, правами та опціями? А все так само дуже просто - розкладанням потрібних файликів у потрібні місця. Починаючи з релізу 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"
А що ж із віджетами, і як вони взагалі виглядають? А ось якось так [[taskbarwidgets|так]].