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

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


development

Розбіжності

Тут показані розбіжності між вибраною ревізією та поточною версією сторінки.

Посилання на цей список змін

Наступна ревізія
Попередня ревізія
development [2022/09/24 14:39]
127.0.0.1 зовнішнє редагування
development [2024/12/23 11:48] (поточний)
nightfly [Розташування модулю як плагіну профілю користувача]
Рядок 1: Рядок 1:
-====== Краткое пособие по разработке модулей для Ubilling ======+====== Короткий посібник із розробки модулів для Ubilling ======
  
-Писать дополнительные модули для Ubilling очень просто, давайте рассмотрим процесс написания простейшего модуля на примере модуля показывающего всех пользователей с ихними ФИО, и адресами в виде красивой сортируемой таблички.+Писати додаткові модулі для Ubilling дуже просто, розгляньмо процес написання найпростішого модуля на прикладі модуля, що показує всіх користувачів з їхніми ПІБ та адресами у вигляді гарної сортувальної таблички.
  
-Типичный модуль Ubilling размещается в отдельном подкаталоге **/modules/general/** и состоит из двух файлов: **index.php** и **module.php**. Первый из них является собственно модулем с его исполняемым кодом, второй же - описанием модуля для встроенного диспатчера. Давайте допустим что наш модуль будет называться samplemod и таким образом будет состоять из двух файлов:\\+Типовий модуль Ubilling розміщується в окремому підкаталозі **/modules/general/** і складається з двох файлів: **index.php** і **module.php**. Перший із них є власне модулем із його виконуваним кодом, другий же - описом модуля для вбудованого диспатчера. Давайте припустимо, що наш модуль називатиметься samplemod і таким чином складатиметься з двох файлів:\\
 \\ \\
 {{:samplemod.png?|}} {{:samplemod.png?|}}
 \\ \\
  
-Давайте подробно разберем что-же находиться в этих двух мистических файликах.\\+Давайте детально розберемо що-ж знаходиться в цих двох містичних файликах.\\
  
 <file php module.php> <file php module.php>
   <?php   <?php
   $this->registerModule($module, 'main', 'Sample module', 'Sample developer', array('SAMPLE' => __('right for access sample module')));   $this->registerModule($module, 'main', 'Sample module', 'Sample developer', array('SAMPLE' => __('right for access sample module')));
-  ?> 
 </file> </file>
  
-Содержит в себе стандартный набор описывающий точто модуль имеет класс **main** (тобишь может размещаться в центральном блоке контента по умолчанию), зовется **Sample module**, написан разработчиком по имени ** Sample developer** и при своей подгрузке порождает право **SAMPLE** по которому в последствии мы будем разграничивать доступ к даному модулюОбратите внимание на конструкцию <code>__('Строка на английском')</code> использованную в даном примере в роли описания права на модуль. Функция будет возвращать локализированную строку относительно текущего языка если она найдена в словарном файлеСобственно локализация в Ubilling является gettext подобной.\\ +Містить у собі стандартний набір, який описує тещо модуль має клас **main** (тобто може розміщуватися в центральному блоці контенту за замовчуванням), зветься **Sample module**, написаний розробником на ім'я **Sample developer** і під час свого довантаження породжує право **SAMPLE**, за яким згодом ми розмежовуватимемо доступ до цього модуляЗверніть увагу на конструкцію <code>__('Рядок англійською')</code> використану в цьому прикладі в ролі опису права на модуль. Функція повертатиме локалізований рядок відносно поточної мови, якщо він знайдений у словниковому файліВласне локалізація в Ubilling є подібною до gettext.\\ 
-Все, с файлом описания модуля разобрались, поехали дальше.\\+Все, з файлом опису модуля розібралися, поїхали далі.\\
 \\ \\
 \\ \\
Рядок 24: Рядок 23:
 <file php index.php> <file php index.php>
 <?php <?php
-  // проверяем имеет ли пользователь права на пользование этим модулем+  // перевіряємо чи має користувач права на користування цим модулем
   if (cfr('SAMPLE')) {   if (cfr('SAMPLE')) {
          
-    //делаем запрос к БД с целью получить логины всех пользователей+    //робимо запит до БД з метою отримати логіни всіх користувачів
     $query="SELECT `login`,`IP` from `users`";     $query="SELECT `login`,`IP` from `users`";
     $alllogins=simple_queryall($query);     $alllogins=simple_queryall($query);
          
-    //получаем масивы всех Ф.И.Опользователей и их адресов+    //отримуємо масиви всіх П.І.Бкористувачів та їхніх адрес
     $allrealnames=zb_UserGetAllRealnames();     $allrealnames=zb_UserGetAllRealnames();
     $alladdress=zb_AddressGetFulladdresslist();     $alladdress=zb_AddressGetFulladdresslist();
          
-    //проверяем, есть ли вообще у нас пользователи+    //перевіряємочи є взагалі у нас користувачі
     if (!empty ($alllogins)) {     if (!empty ($alllogins)) {
                          
-            //Собираем заголовок таблички для вывода+            //Збираємо заголовок таблички для виведення
             $tablecells=wf_TableCell(__('Login'));             $tablecells=wf_TableCell(__('Login'));
             $tablecells.=wf_TableCell(__('IP'));             $tablecells.=wf_TableCell(__('IP'));
Рядок 45: Рядок 44:
             $tablerows=wf_TableRow($tablecells, 'row1');             $tablerows=wf_TableRow($tablecells, 'row1');
                  
-        // Перебираем всех пользователей+        // Перебираємо всіх користувачів
         foreach ($alllogins as $io=>$eachlogin) {         foreach ($alllogins as $io=>$eachlogin) {
             $userlogin=$eachlogin['login'];             $userlogin=$eachlogin['login'];
             $userip=$eachlogin['IP'];             $userip=$eachlogin['IP'];
                          
-            //Собирая для каждого строки таблички+            //Збираючи для кожного рядка таблички
             $tablecells=wf_TableCell($userlogin);             $tablecells=wf_TableCell($userlogin);
             $tablecells.=wf_TableCell($userip);             $tablecells.=wf_TableCell($userip);
Рядок 58: Рядок 57:
         }         }
                  
-        // объявляем как результат табличку с предварительно собранными строками +        // оголошуємо як результат табличку з попередньо зібраними рядками 
-        // а также шириной в 100%, бордюром в 0 и классом sotrable+        // а також шириною в 100%, бордюром в 0 і класом sotrable
         $result=wf_TableBody($tablerows, '100%', '0', 'sortable');         $result=wf_TableBody($tablerows, '100%', '0', 'sortable');
                  
     } else {     } else {
-        //если нету намекаем что их нету+        //якщо немає натякаємо що їх немає
         $result=__('No users found');         $result=__('No users found');
     }     }
          
-    // выводим наш результат при помощи функции show_window+    // виводимо наш результат за допомогою функції show_window
     show_window(__('Sample module'), $result);     show_window(__('Sample module'), $result);
        
          
   } else {   } else {
-      // если нет - вываливаем на него ошибку об отказе в доступе+      // якщо ні - вивалюємо на нього помилку про відмову в доступі
       show_error(__('You cant control this module'));       show_error(__('You cant control this module'));
   }   }
- 
-?> 
  
 </file> </file>
    
-Доступ к нашему модулю мы можем получить при помощи ссылки **?module=samplemod** в результате чего мы должны увидеть приблизительно следующее:\\+Доступ до нашого модуля ми можемо отримати за допомогою посилання **?module=samplemod**в результаті чого ми повинні побачити приблизно таке:\\
  
 {{:samplemod2.png?|}} {{:samplemod2.png?|}}
  
-Как видите вместо строк **Real Name** и **Address** у нас автоматически подставились их языко-зависимые замены из словаря текущей локализации. Не переведенной осталась одна строка **Sample module** о которой движок локализации пока что ничего не знает. Давайте переведем ее скажем на русский язык для начала.\\ +Як бачите, замість рядків **Real Name** і **Address** у нас автоматично підставилися їхні мовно-залежні заміни зі словника поточної локалізації. Не перекладеним залишився один рядок **Sample module**, про який рушій локалізації поки що нічого не знає. Давайте перекладемо його скажімо російською мовою для початку.\\\ 
-Сделать это довольно просто - нужно создать файл **/languages/russian/samplemod.php** следующего содержания:+Зробити це досить просто - потрібно створити файл **/languages/ukrainian/samplemod.php** такого змісту:
  
 <file php samplemod.php> <file php samplemod.php>
 <?php <?php
-$lang['def']['Sample module'] = 'Модуль для примера'; +$lang['def']['Sample module'] = 'Модуль для прикладу'; 
-$lang['def']['Yet another string'] = 'Еще какая-то строка'; +$lang['def']['Yet another string'] = 'Ще якийсь рядок'; 
-?>+
 </file> </file>
  
-После чего мы увидим как строка локализовалась сама по себе в нашем модуле:\\+Після чого ми побачимо як рядок локалізувався сам по собі в нашому модулі:\\
  
 {{:samplemod3.png?|}} {{:samplemod3.png?|}}
  
 \\ \\
-Из нестандартных вещей чуждых чистому PHP мы использовали только функции библиотеки** api.astral** для сборки таблиц при помощи **wf_** что не является объязательным, просто выглядит красивее и читабельнее, а также вывод сквозь **show_window($title,$data)** вместо **print()** что уже является объязательным для работы шаблонизатора фреймворка.\\+З нестандартних речейчужих чистому PHPми використовували тільки функції бібліотеки** api.astral** для збирання таблиць за допомогою **wf_**, що не є обов'язковою, просто виглядає красивіше та читабельніше, а також результат крізь **show_window($title,$data)** замість **print()**, що вже є обов'язковою для роботи шаблонізатора фреймворка.\\
  
-А что делатьесли нашему модулю требуется какая-то библиотека/класс нужная ему одному? Вариантов есть несколько. Первый из них менее красивый но более портабельный - вставить ее прямо внутрь нашего модуля в **modules/general/smaplemod/index.php**. Второй - просто положить эту библиотеку в директорию **modules/engine/**. В этом случае она будет подгружена до выполнения нашего модуля. Хорошим тоном в этом случае будет убедиться, что при своей загрузке она не будет производить какого-то вывода и второе - постарайтесь избегать создания больших объектов в этой библиотекечтобы избежать деградации производительности в целом. Что подразумевается под этим? Приведем на примере библиотеки, которая описывает некий класс SampleClass и находится в **modules/engine/sampleClass.php**+А що робитиякщо нашому модулю потрібна якась бібліотека/клас потрібна йому одному? Варіантів є кілька. Перший з них менш красивий, але більш портабельний - вставити її прямо всередину нашого модуля в **modules/general/samplemod/index.php**. Другий - просто покласти цю бібліотеку в директорію **modules/engine/**. У цьому разі вона буде довантажена до виконання нашого модуля. Хорошим тоном у цьому випадку буде переконатися, що під час свого завантаження вона не буде виробляти якогось виводу, і друге - постарайтеся уникати створення великих обктів у цій бібліотеціщоб уникнути деградації продуктивності загалом. Що мається на увазі під цим? Наведемо на прикладі бібліотеки, яка описує якийсь клас SampleClass і знаходиться в **modules/engine/sampleClass.php**
  
 <file php sampleClass.php> <file php sampleClass.php>
Рядок 120: Рядок 117:
 } }
  
-$sampleObject=new SampleClass(); // вот этого тут быть не должно - ему место в modules/general/samplemod/index.php+$sampleObject=new SampleClass(); // ось цього тут бути не повинномісце йому в modules/general/samplemod/index.php
  
 ?> ?>
 </file> </file>
  
-Также отличным (**и рекомендуемым!**)способом может быть помещение вашей библиотеки в **api/libs/** откуда ее может подхватить автозагрузчик, в случае если имя класса создаваемого объекта соответствует имени библиотеки с префксом "**api.**" в лаверкейсе. Для примера выше это должен быть файл **api/libs/api.sampleclass.php**. При создании объекта $sampleObject=new SampleClass(); эта библиотека будет автоматически загруженаи вам вообще ничего не нужно для этого делать. Данная механика появилась начиная с релиза Ubilling 0.8.6 Chainsaw.+Також чудовим (**і рекомендованим!**) способом може бути розміщення вашої бібліотеки в **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/**+====== Розташування модуля на панелі задач ====== 
 + 
 +А як додаються модулі на панель завдань? Ну там з іконками, правами та опціями? А все так само дуже просто - розкладанням потрібних файликів у потрібні місцяПочинаючи з релізу 0.8.0 цими місцями є директорія **config/taskbar.d/**, а точніше її підкаталоги. Припустимо, наш тестовий модуль є з нашої точки зору звітом. Також ми хочемощоб вмикався він за допомогою необов'язкової опції [[alteriniconf|alter.ini]] на ім'я SAMPLE_ENABLED. Разом кладемо файлик sample.ini в директорію **config/taskbar.d/reports/**
  
 <file ini sample.ini> <file ini sample.ini>
-Идентификатор модуля. Должен быть как минимум уникальным.+Ідентифікатор модуля. Повинен бути як мінімум унікальним.
 ID="samplemod" ID="samplemod"
-; Подпись иконки модуля - будет автоматически локализирована текущей локалью.+; Підпис іконки модуля - буде автоматично локалізовано поточною локаллю.
 NAME="Sample module" NAME="Sample module"
-; URL нашего модуля. Не поверите - будет кликабельным :)+; URL нашого модуля. Не повірите - буде клікабельним :)
 URL="?module=samplemod" URL="?module=samplemod"
-Иконка модуля. Сначала пытается найтись в директории taskbar текущего скина, если не существует - в глобальном skins/taskbar.+Іконка модуля. Спочатку намагається знайтися в директорії taskbar поточного скіна, якщо не існує - у глобальному skins/taskbar.
 ICON="goat.gif" ICON="goat.gif"
-; Право которое требует модуль. Ну как минимум право которое требуется для показа иконки.+; Право, яке вимагає модуль. Ну як мінімум право, яке потрібне для показу іконки.
 NEED_RIGHT="SAMPLE" NEED_RIGHT="SAMPLE"
-; Опция конфига alter.ini требуемая для показа иконки таскбара.+; Опція конфіга alter.ini необхідна для показу іконки таскбару.
 NEED_OPTION="SAMPLE_ENABLED" NEED_OPTION="SAMPLE_ENABLED"
-Данный параметр сигнализируетчто опция является необязательной.  +Цей параметр сигналізуєщо опція є необов'язковою.  
-Если удалить данный параметр - панель задач будет орать о недостающей опции.+Якщо видалити цей параметр - панель завдань буде кричати про відсутню опцію.
 UNIMPORTANT=1 UNIMPORTANT=1
-; Тип елемента. В нашем случае это icon - типичная иконка с подписьюЕсть еще widget но о этом позже.+; Тип елемента. У нашому випадку це icon - типова іконка з підписомЄ ще widget але про це пізніше.
 TYPE="icon" TYPE="icon"
 +; Ця необов'язкова опція описує те буде відкриватись посилання на елемент. 
 +; Може бути відсутньою чи порожньою або приймати значення _blank, _self, _parent, _top чи ім'я iframe. 
 +; детальніше тут: https://www.w3schools.com/tags/att_a_target.asp
 +LINK_TARGET=
 +</file>
 +
 +та отримуємо результат очікуваний результат
 +
 +{{:undefined:samplemod4.png|}}
 +
 +А що ж із віджетами, і як вони взагалі виглядають? А ось якось так [[taskbarwidgets|так]].
 +
 +====== Приклад використання dataTable ======
 +
 +<code php>
 +   // 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();
 +    }
 +</code>
 +
 +
 +результат
 +
 +{{:jqdt.png|}}
 +
 +====== Розташування модулю як плагіну профілю користувача ======
 +Формат plugins.ini дуже близький до формату опису елементу панелі задач. Тільки імена опцій в лаверкейсі.
 +
 +<file ini plugins.ini>
 +[унікальний ідентифікатор модуля]
 +name = "Ім'я модулю"
 +icon = "ім'я файлу іконки модулю"
 +need_right=Право яке необхідне модулю
 +need_option=Опція яка необхідна
 +;Наступна опція не є обов`язковою. Просто вказує те де буде відкрито посилання.
 +;детальніше тут: https://www.w3schools.com/tags/att_a_target.asp
 +;link_target=_self
 </file> </file>
  
-А что же с виджетамии как они вообще выглядят? А вот как-то [[taskbarwidgets|так]].+також модуль може бути описаним у оверлеї "чорної магії" в bmagic.ini в тому ж форматі.
development.1664019551.txt.gz · Востаннє змінено: 2022/09/24 14:39 повз 127.0.0.1