Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Мануал по работе с фреймворком ABillS

Мануал разработчика

Форматирование кода

...

Форматирование if else:

Code Block
languageperl
if (expr) {
  ...
}
else {
  ...
}

Однострочные или-выражения

Всегда выражения берутся в скобки

Code Block
languageperl
$result = ($total_users == 1) ? "Ok" : "Fail";

print "test" if ($test == 1);

Переменные

Переменные указываются строчными буками

Code Block
languageperl
  $test, @devices, %switch

Объекты указываются с заглавной

Code Block
languageperl
$Test = Test->new();

Массивы указываются в множественном числе

Code Block
languageperl
my @devices = ();
my @users = ();

Хеши в единственном

Code Block
languageperl
%status_list = ();
$status_list{disable}=1;

Общий шаблон функций

Code Block
languageperl
#**********************************************************
=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;
}

Рекомендации:

  1. Отделяйте шапки функций звёздочками (58 штук).
  2. Не игнорируйте создание комментариев перед началом функции.
  3. Называйте функции строчными буквами с разделением нижним подчёркиванием.
  4. По умолчанию, в случае успешного выполнения функция должна возвращать 1, в случае ошибки - 0.

  5. Минимизируйте использование глобальных переменных в функциях.

Дата обновления в шапке модуля

Дату обновления модуля следует указывать в шапке модуля (в начале файла) в формате YYYYMMDD.

Пример:

Code Block
languageperl
=head1 Cdata

  C-data
  MODEL:
    epon
      FD1104SN
  ...

  DATE: 20190704
  UPDATE: 20210324

=cut

DATE - дата создания модуля

UPDATE - дата обновления модуля

Указывать дату правильно важно для коммерческих модулей, так как скрипт обновления update.sh ожидает увидеть дату в этом формате.

Можно ли использовать HTML в коде?

Ни в коем случае не используйте HTML в коде управляющей модели, вместо этого используйте объекты Abills::HTML или шаблоны.

Дополнительные модули

Загрузка дополнительных модулей Perl осуществляется командой

Code Block
languageperl
load_pmodule('Simple::XML');

(Библиотека Misc.pm)

С проверкой ошибок код выглядит так:

Code Block
languageperl
my $loaded_imager_error = load_pmodule( "Imager", { RETURN => 1 } );
if ( $loaded_imager_error ) {
  print $loaded_imager_error;
  return 0;
}

Дополнительные модули с автоустановкой

Загрузка дополнительных модулей Perl с автоустановкой осуществляется командой

Code Block
languageperl
load_perl_module('SQL::Translator');
(Библиотека PModules.pm)

Поиск в полях

Для удобства поиска было разработано несколько разделителей.

Для цифровых полей

Разделитель запятая (,) обозначает AND.

Пример: искать значения поля 56 и 66

Code Block
languagetext
56,66

Разделитель точка с запятой (;) обозначает OR.

Пример: искать значения поля 56 или 66

Code Block
languagetext
56;66

Тестирование

Для тестирования системы существует каталог с тестами abills/t.

Code Block
languagebash
make

Жесткий тест работоспособности, никогда его не выполняйте на рабочей системе, чревато пропажей данных

Code Block
languagebash
perl web.t brutal

тестирование синтаксиса и стресс-тест веб-приложений

Warning

НЕ ИСПОЛЬЗОВАТЬ НА ПРОДАКШН СИСТЕМЕ

Тест проверки авторизации и аккаунтинга

Code Block
languagebash
t/Aaa.t

Проверка DHCP авторизации используя приготовленный RAD PAIRS пакет dhcp.discover

Code Block
languagebash
perl Aaa.t dhcp_test dhcp.discovery

Тестирование абон. платы тарифного плана

Code Block
languagebash
perl Tariffs.t FILENAME=tp_test1.tp

FILENAME - файл с описанием тарифного плана и параметров абонента.

Для задания логина и пароля авторизации используется файл t/.test

Code Block
languagetext
login:password

В системе также есть специальный скрипт запуска выделенных тестов, которые хранятся в отдельных каталогах: Запуск тестов для модуля или папки

Создание демона

Code Block
languageperl
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.

Пример:

Code Block
languageperl
$lang{LANG_MARKER} = 'Языковой маркер';

Названия маркеров обязательно писать заглавными буквами.

Отображение в шаблонах:

Code Block
languagetext
_{LANG_MARKER}_

Переменные внутри lang

Code Block
languageperl
$lang{LANG_MARKER_WITH_VARS} = 'У абонента минус %DEPOSIT%';

И использовать функцию:

Code Block
languageperl
use Abills::Base qw(vars2lang);

vars2lang($lang{LANG_MARKER_WITH_VARS}, { DEPOSIT => '5' });

Но, конечно, вы можете использовать любой string с такой разметкой.

JSON тестирование

Для того, чтобы протестировать функцию:

...

Подключите JSON.t

Code Block
languageperl
require "./JSON.t";

Создайте JSON, заполнив его. API_KEY - ключ API текущего администратора

Code Block
languageperl
my @test_list = (
  {
    name       => 'InfoFields',
    params     => {
      qindex       => 96,
      API_KEY      => '1523615231263123',
      json         => 1
    },
    result     => '',
    valid_json => 1,
    schema     => {
 
    }
  }
  );

Передайте данные в функцию json_test

Code Block
languageperl
json_test(
  \@test_list, 
  { TEST_NAME => 'info_fields_new test' });

Выполните ваш тест, запустив программу

Code Block
languagebash
# prove -v <название теста>.t

String Eval

Когда нужно загрузить динамически модуль необходимо его загрузить следующим образом

Code Block
languageperl
my $module = 'Example';
eval "use $module";

Но настоятельно не рекомендуется это делать в Perl. Потому нужно использовать следующий вариант

Code Block
languageperl
my $module_name = 'Example';
eval {
  my $module = "$module_name.pm";
  require $module;
  $module->import();
  1;
};

Если модуль имеет назву с названием директории пример

Module::Example

Тогда нужно получить последнее слово модуля, это его название

Code Block
languageperl
my $module_full_name = 'Module::Example';
my ($module_name) = $module_full_name =~ /(\w+)$/;

eval {
  my $module = "$module_name.pm";
  require $module;
  $module->import();
  1;
};

Конфигурационные переменные

Здесь описаны правила при заполнении конфигурационных переменных.

  1. Если ваша переменная должна иметь изначальное значение (fallback), то нужно её добавить в функцию _fill_conf_defaults.