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

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


Сайдбар

Розділи

Загальний опис
Історія змін
Рекомендації до оновлення
Плани на майбутнє
Відомі проблеми
Онлайн демо
Допомога проекту
Люди
Трохи про безпеку

FAQ



Редагувати сайдбар

stigma

API Stigma

В Ubilling починаючи зі стабільного релізу 1.2.0 з'явилася можливість використовувати у ваших модулях загальну реалізацію стигматизації об'єктів. Власне, стигми являють собою якісь стани якихось рандомних об'єктів (items) у межах якоїсь рандомної категорії (scope). Використання API Stigma найближче за духом до API ADcomments.

Найпростіше пояснити роботу цього механізму на прикладі “а давайте зробимо можливість десь, у якомусь нашому модулі, відзначати, чи купив користувач у нас роутер, чи він жадібна свиня?”. Конфігурація цієї стигми починається з написання конфігураційного файлу, який зберігатиметься в config/stigma/, нехай це буде userbuyrouter.ini через запланований нами SCOPE “USERBUYROUTER”. Так, ім'я файлика конфігурації стигми для конкретного scope-а за замовчуванням - це цей самий scope у lowercase із розширенням *.ini. Власне він і буде у нас читатися при створенні об'єкта стигми з відповідним SCOPE.

userbuyrouter.ini
[stigmasettings]
TYPE=radiolist
BASECLASS=dashtask
ACTIVECLASS=todaysig
ANIMATION=1
RENDERER=iconic
 
[buy]
NAME="Bought a router"
ICON=sellrouter
 
[nobuy]
NAME="Greedy pig"
ICON=pig
 
[unknown]
NAME="We dont know"

Коротко про формат конфігурації

Секція “stigmasettings” є службовою та обов'язковою. Вона вказує на базову поведінку контролів у конкретному скоупі. Можливі типи (TYPE) на даний момент “radiolist” (вибір одного з усіх) або “checklist” (множинна вибірка). ANIMATION просто вказує, чи оновлювати з супутньою анімацією контейнер стигмати під час зміни стану, чи робити це “тихо і непомітно”. Оскільки стан “купив у нас роутер” не може бути одночасно і “купив”, і “не купив”, ми використовуємо тип “radiolist”. Опція ACTIVECLASS вказує просто, яким CSS-класом будуть підсвічуватися активні/вибрані стани об'єктів у межах цього scope. Починаючи з Ubilling 1.4.1 також можна опційно вказувати і BASECLASS, який буде використовуватись для всіх контролів за замовчуванням. Так, це теж ім'я CSS класу.

Далі всі секції, які не є stigmasettings, описують конкретні стани об'єктів (items) у межах конкретного SCOPE. Їх може бути скільки завгодно. Ім'я секції власне буде ідентифікатором стану, що зберігається в БД, і має бути якомога коротшим та унікальним. Базовими характеристиками стану крім його ідентифікатора є NAME (ім'я) і ICON (ви не повірите! іконка). Іконки станів за замовчуванням зберігаються в skins/stigma/ з розширенням *.png.

Крім усього цього, реалізовано механіку підвантаження кастомних файлів конфігурації та іконок, на випадок якщо користувачі самі захочуть розширити набір станів, або замінити іконки на якісь свої, і щоб це все пережило оновлення. Кастомні файли конфігурації та іконки, що мають пріоритет над замовчуваними, зберігатимуться в content/documents/mystigma у сабдиректоріях confs і icons

Практичне використання в коді

Повертаючись до початкової задачі, ми хочемо ловити GET параметром логін якогось користувача і виставляти йому стан.

  if (ubRouting::checkGet('username')) {
        $userLogin = ubRouting::get('username');
 
        //створюємо інстанс із потрібним нам scope-ом.
        $userRouter = new Stigma('USERBUYROUTER');
        //викличемо обробник фонових коллбеків на випадок, якщо у нас зміниться стан
        $userRouter->stigmaController();
        //показуємо інтерфейс зміни стану для нашого конкретного користувача
        show_window(__('User bought a router'), $userRouter->render($userLogin));
    }

Ну і власне одразу отримуємо результат у вигляді панелі управління станами користувача.

А може хочемо меншу панельку?

show_window(__('User bought a router'), $userRouter->render($userLogin, '64'));

типу такої?

А може хочемо read-only панельку для адміністраторів без якогось права, але яка нормально працює для адміністраторів, наділених цими правами? Тоді якось так

    if (ubRouting::checkGet('username')) {
        $userLogin = ubRouting::get('username');
        $userRouter = new Stigma('USERBUYROUTER');
        $userRouterReadOnlyFlag = true;
        if (cfr('USERROUTEREDIT')) {
            $userRouter->stigmaController();
            $userRouterReadOnlyFlag = false;
        }
 
        show_window(__('User bought a router'), $userRouter->render($userLogin, '64', $userRouterReadOnlyFlag));
    }

А якщо ми хочемо просто десь в іншому місці показати тупо список наявних станів цього користувача?

show_window(__('User bought a router as text'), $userRouter->textRender($userLogin);

типу так

чи взагалі тупо перевірити чи є якісь встановлені стани й отримати їх у вигляді масиву для наших подальших дофіга концептуальних бізнес-додатків?

 if ($userRouter->haveState($userLogin)) {
            $routerStates = $userRouter->getItemStates($userLogin);
        }

А ще ми можемо отримати всі можливі для скоупа стани з їхніми текстовими описами ось якось так

$userRouter = new Stigma('USERBUYROUTER');
$allStates=$userRouter->getAllStates();
debarr($allStates);

Коротше все настільки прямолінійно і брутально, наскільки це можливо. А взагалі поглянути на публічні методи і що у них у параметрах буде набагато продуктивніше і зрозуміліше.

Про оптимізацію швидкодії

У прикладі вище, ми створювали інстанс стигми як

$userRouter = new Stigma('USERBUYROUTER');

Що зі свого боку завантажувало з бази всі стани всіх айтемів у цьому scop-і. Це може бути корисно, коли ми одним і тим самим інстансом намагаємося працювати з різними айтемами одним інстансом. Наприклад читаючи/перевіряючи наявність станів для різних айтемів одним і тим же інстансом. Типу як

 $allUsers = zb_UserGetAllDataCache();
 $userRouter = new Stigma('USERBUYROUTER');
 
    if (!empty($allUsers)) {
        foreach ($allUsers as $eachLogin => $eachData) {
            if ($userRouter->haveState($eachLogin)) {
                $routerStates = $userRouter->getItemStates($eachLogin);
 
                if (isset($routerStates['buy'])) {
                    show_success($eachLogin);
                }
 
                if (isset($routerStates['nobuy'])) {
                    show_warning($eachLogin . ' ' . __('gotcha!'));
                }
            }
        }
    }

але в нашому першому прикладі, логічно було б завантажувати з БД тільки стан одного конкретного, що цікавить нас айтема, а точніше, конкретного користувача, якого ми зловили в GET-параметрі username. У такому разі створення нашого інстансу мало б виглядати так:

   $userRouter = new Stigma('USERBUYROUTER', $userLogin);

що призведе до завантаження даних про стани тільки для айтема $userLogin у межах scop-а USERBUYROUTER у процесі створення інстансу, і цілком собі дасть нам змогу з ними працювати. Але тільки ось для цього конкретного $userLogin.

Логування змін станів

Базово, підтримується три різноманітні режими логування змін станів, якщо вам це необхідно: TASKMAN, SYSTEM, CUSTOM.

  • TASKMAN:[стан] - запис до логу “Планування робіт”.
  • SYSTEM:[стан] - запис до системного журналу подій.
  • CUSTOM:[таблиця] - запис до довільної таблиці в БД.

Для логування до довільної таблиці, її структура має мати наступний формат:

CREATE TABLE IF NOT EXISTS `somecustomlog` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `date` datetime NOT NULL,
  `admin` VARCHAR(64) DEFAULT NULL,
  `scope` VARCHAR(64) DEFAULT NULL,
  `itemid` VARCHAR(128) NOT NULL,
  `action` VARCHAR(32) DEFAULT NULL,
  `state` VARCHAR(255) DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `scope` (`scope`),
   KEY `itemid` (`itemid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

Логування TASKMAN: ви не використовуватимете з ймовірністю 99%, з логуванням SYSTEM:[стан] який ви можете ввімкнути при виклику обробника коллбеків, наступним чином:

   $leadSource->stigmaController('SYSTEM:якийсь_стан');

в системному лозі з'являтимуться записи наступного вигляду

STIGMA [поточний_SCOPE] CHANGE [ідентифікатор_айтема] `[якийсь_стан]` ON `[ідентифікатор_стану]`

Чим буде заповнюватись табличка somecustomlog при логуванні CUSTOM:somecustomlog викликаному отак:

   $leadSource->stigmaController('CUSTOM:somecustomlog');

теж доволі зрозуміло з іменування її полів.

Типи рендерингу

Починаючи з Ubilling 1.4.1 в секції конфігурації [stigmasettings] також можна опційно встановити опцію RENDERER, яка прямо вказує на тип відображення контролів конкретної стигми.

Можливі значення опції на даний момент:

  • iconic - рендерер, за замовчуванням у вигляді “натискаємих іконок”. Він же використовується у випадку якщо опція RENDERER відсутня.
  • selector - просто стандартний селектор у вигляді “вибирушки”. Працює тільки з TYPE=radiolist, що доволі очевидно.
  • textlink - зображає всі наявні стани в скоупі у вигляді простих текстових посилань.
  • imagelink - зображає всі наявні стани в скоупі у вигляді простих текстових посилань з маленькими іконками станів.
stigma.txt · Востаннє змінено: 2023/11/04 13:10 повз nightfly