====== Короткий посібник із розроблення модулів для 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|так]].