Инструменты пользователя

Инструменты сайта


Боковая панель

Разделы

Общее описание
История изменений
Рекомендации к обновлению
Планы на будущее
Известные проблемы
Онлайн демо
Случайная статья
Видео
Помощь проекту
Люди

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/russian/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/smaplemod/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(); эта библиотека будет автоматически загружена, и вам вообще ничего не нужно для этого делать. Данная механика появилась начиная с релиза Ubilling 0.8.6 Chainsaw.

А как добавляются модули на панель задач? Ну там с иконками, правами и опциями? А все так же очень просто - расскладыванием нужных файликов в нужные места. Начиная с релиза 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"

А что же с виджетами, и как они вообще выглядят? А вот как-то так.

development.txt · Последние изменения: 2019/02/22 02:51 — nightfly