Мануал по работе с фреймворком ABillS
Форматирование кода
- Для отступов не использовать табуляций, только двойные пробелы
Форматирование if else:
if (expr) { ... } else { ... }
Однострочные или-выражения
Всегда выражения берутся в скобки
$result = ($total_users == 1) ? "Ok" : "Fail"; print "test" if ($test == 1);
- Для удобства форматирования кода можно воспользоваться утилитой perltidy
https://support.abills.net.ua/perltidy.cgi
Переменные
Переменные указываются строчными буками
$test, @devices, %switch
Объекты указываются с заглавной
$Test = Test->new();
Массивы указываются в множественном числе
my @devices = (); my @users = ();
Хеши в единственном
%status_list = (); $status_list{disable}=1;
Общий шаблон функций
#**********************************************************
=head2 test_function($attr) - Test function
Arguments:
$attr - Extra attributes
TEXT - Some text
Returns:
TRUE or FALSE
Example:
test_function({ TEXT => 'Some text' });
=cut
#**********************************************************
sub test_function {
my ($attr) = @_;
print "Hello world!";
return 1;
}
Рекомендации:
- Отделяйте шапки функций звёздочками (58 штук).
- Не игнорируйте создание комментариев перед началом функции.
- Называйте функции строчными буквами с разделением нижним подчёркиванием.
По умолчанию, в случае успешного выполнения функция должна возвращать 1, в случае ошибки - 0.
Минимизируйте использование глобальных переменных в функциях.
Дата обновления в шапке модуля
Дату обновления модуля следует указывать в шапке модуля (в начале файла) в формате YYYYMMDD.
Пример:
=head1 Cdata
C-data
MODEL:
epon
FD1104SN
...
DATE: 20190704
UPDATE: 20210324
=cut
DATE - дата создания модуля
UPDATE - дата обновления модуля
Указывать дату правильно важно для коммерческих модулей, так как скрипт обновления update.sh ожидает увидеть дату в этом формате.
Можно ли использовать HTML в коде?
Ни в коем случае не используйте HTML в коде управляющей модели, вместо этого используйте объекты Abills::HTML или шаблоны.
Дополнительные модули
Загрузка дополнительных модулей Perl осуществляется командой
load_pmodule('Simple::XML');
(Библиотека Misc.pm)
С проверкой ошибок код выглядит так:
my $loaded_imager_error = load_pmodule( "Imager", { RETURN => 1 } );
if ( $loaded_imager_error ) {
print $loaded_imager_error;
return 0;
}
Дополнительные модули с автоустановкой
Загрузка дополнительных модулей Perl с автоустановкой осуществляется командой
load_perl_module('SQL::Translator');
(Библиотека PModules.pm)Поиск в полях
Для удобства поиска было разработано несколько разделителей.
Для цифровых полей
Разделитель запятая (,) обозначает AND.
Пример: искать значения поля 56 и 66
56,66
Разделитель точка с запятой (;) обозначает OR.
Пример: искать значения поля 56 или 66
56;66
Тестирование
Для тестирования системы существует каталог с тестами abills/t.
make
Жесткий тест работоспособности, никогда его не выполняйте на рабочей системе, чревато пропажей данных
perl web.t brutal
тестирование синтаксиса и стресс-тест веб-приложений
НЕ ИСПОЛЬЗОВАТЬ НА ПРОДАКШН СИСТЕМЕ
Тест проверки авторизации и аккаунтинга
t/Aaa.t
Проверка DHCP авторизации используя приготовленный RAD PAIRS пакет dhcp.discover
perl Aaa.t dhcp_test dhcp.discovery
Тестирование абон. платы тарифного плана
perl Tariffs.t FILENAME=tp_test1.tp
FILENAME - файл с описанием тарифного плана и параметров абонента.
Для задания логина и пароля авторизации используется файл t/.test
login:password
В системе также есть специальный скрипт запуска выделенных тестов, которые хранятся в отдельных каталогах: Запуск тестов для модуля или папки
Создание демона
use Abills::Base;
use Abills::Server;
my $ARGV = parse_arguments(\@ARGV);
# Демонизация и ведение лога
if (defined($ARGV->{'-d'})) {
my $pid_file = daemonize();
#ведение лога
#$Log->log_print('LOG_EMERG', '', "$prog_name Daemonize... $pid_file");
}
# Остановка процесса
elsif (defined($ARGV->{stop})) {
stop_server();
exit;
}
# Проверка, не запущен ли уже
elsif (make_pid() == 1) {
exit;
}
# Таймаут между запусками 100 секунд
my $UPDATE_TIME=100;
while (1) {
check_activity({ ALL => ($ARGV->{RECONFIG_PERIOD}) ? undef : $all });
sleep $UPDATE_TIME;
Языковые маркеры
Сохраняются в глобальном хеше %lang.
Пример:
$lang{LANG_MARKER} = 'Языковой маркер';
Названия маркеров обязательно писать заглавными буквами.
Отображение в шаблонах:
_{LANG_MARKER}_
Переменные внутри lang
$lang{LANG_MARKER_WITH_VARS} = 'У абонента минус %DEPOSIT%';
И использовать функцию:
use Abills::Base qw(vars2lang);
vars2lang($lang{LANG_MARKER_WITH_VARS}, { DEPOSIT => '5' });
Но, конечно, вы можете использовать любой string с такой разметкой.
JSON тестирование
Для того, чтобы протестировать функцию:
- Создайте тест в /usr/abills/t
Подключите JSON.t
require "./JSON.t";
Создайте JSON, заполнив его. API_KEY - ключ API текущего администратора
my @test_list = ( { name => 'InfoFields', params => { qindex => 96, API_KEY => '1523615231263123', json => 1 }, result => '', valid_json => 1, schema => { } } );Передайте данные в функцию json_test
json_test( \@test_list, { TEST_NAME => 'info_fields_new test' });Выполните ваш тест, запустив программу
# prove -v <название теста>.t
String Eval
Когда нужно загрузить динамически модуль необходимо его загрузить следующим образом
my $module = 'Example'; eval "use $module";
Но настоятельно не рекомендуется это делать в Perl. Потому нужно использовать следующий вариант
my $module_name = 'Example';
eval {
my $module = "$module_name.pm";
require $module;
$module->import();
1;
};
Если модуль имеет назву с названием директории пример
Module::Example
Тогда нужно получить последнее слово модуля, это его название
my $module_full_name = 'Module::Example';
my ($module_name) = $module_full_name =~ /(\w+)$/;
eval {
my $module = "$module_name.pm";
require $module;
$module->import();
1;
};
Конфигурационные переменные
Здесь описаны правила при заполнении конфигурационных переменных.
- Если ваша переменная должна иметь изначальное значение (fallback), то нужно её добавить в функцию _fill_conf_defaults.