Webboard

Pełna wersja: O pisaniu pluginów słów kilka
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Z góry uprzedzam, że poradnik nie jest w języku łopatologicznym. Osoby nie znające PHP (strukturalnie i choć trochę obiektowo) przed przeczytaniem poradnika zapraszam do księgarni po jakąś książkę celem edukacji wstępnej ;)

1 Czym są hooki?


Pluginy w MyBB potrafią rządzić danymi latającymi na drodze forum-użytkownik w tę i z powrotem za pomocą hooków. Hook (ang. hak) jak sama nazwa wskazuje pozwala nam "zahaczyć" się w jakimś miejscu forum, zrobić małe fiki-miki biegającym wokół tego miejsca danym, i wypuścić je w dalszą drogę.

2 Nazywanie pluginów


Pluginem jest plik *.php o odpowiedniej strukturze. Postaram się ją nieco omówić.

Nazwa - nazwa pliku z pluginem nie może być przypadkowa. Swojemu pluginowi musimy wymyślić nazwę "surową", a więc bez kalafiorów w postaci spacji, kropek itp.; spełniającą kryteria nazywania funkcji w PHP - na przykład "uczesie". Taki plugin zapiszemy w pliku "uczesie.php". Nazwą "uczesie" będziemy też zaczynać wszystkie funkcje plugina. Oczywiście, dystrybuować plugin możemy pod nazwą bardziej marketingowo poprawną, np. "Uczę się 1.1 XP Beta" ;)

3 Bezpieczeństwo

 
Pierwsze, co plugin powinien robić, to sprawdzić, czy nie został brutalnie wyciągnięty za fraki z reszty mechanizmu. Sprawdzamy więc, czy stała, która jest definiowana gdzieś w plikach jądra forum, jest zdefiniowana - niech to będą pierwsze linijki plugina.
Kod PHP:
if(!defined("IN_MYBB"))
{
 die(
"Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined.");


4 "Kim ja jestem?" - Opis wtyczki

 
Plugin musi umieć się przedstawić użytkownikowi w Panelu Admina. Będzie to robił za pomocą funkcji nazwaplugina_info(). Funkcja zawsze ma zwracać tablicę asocjacyjną o takiej samej strukturze:
Kod PHP:
function uczesie_info()
{
 return array(
 
"name" => "Uczę się",
 
"description" => "Miejsce na opis plugina. Ja się uczę, więc wiele pisał nie będę.
 Ale warto wiedzieć, że <b>można tu używać HTMLa</b>!"
,
 
"website" => "http://adres.strony.plugna.com/moze-pozostac-pusty",
 
"author" => "twój nick",
 
"authorsite" => "http://adres.twojej.strony.domowej.com/moze-pozostac-pusty",
 
"version" => "wersja 1.2",
 );


5  Aktywacja i dezaktywacja wtyczki


Nasz plik musi też zawierać funkcje, które będą wywoływane w momencie aktywacji i dezaktywacji. Przydaje się to, jeśli plugin tworzy sobie jakieś dodatkowe tabelki albo kolumny w bazie danych - dzięki temu sam może sobie uwić gniazdko, a później po sobie posprzątać. Póki co - niech te funkcje u nas będą puste.
Kod PHP:
function uczesie_activate()
{

}

function 
uczesie_deactivate()
{



6 Hooki 


Przechodzimy do sedna sprawy. W tym momencie musimy już wiedzieć, co nasz plugin ma robić. W przykładzie zajmiemy się najpierw doklejaniem jakiejś frazy do każdego wysyłanego posta, a później zmodyfikujemy kod i będziemy ją doklejać do co drugiego posta użytkownika.

Skoro mamy wprowadzać zmiany w wysyłanym poście, odszukajmy hook, którym zahaczymy się w miejscu, gdzie nowy post jest dodawany do bazy. W tym celu przyda się troszkę intuicji i umiejętności czytania cudzego kodu.

Wszystko, co jest dodawane do bazy w MyBB, jest najpierw filtrowane przez klasę DataHandler i jej rozszerzenia. Postami zajmuje się klasa
Kod PHP:
class PostDataHandler extends DataHandler 
umieszczona w pliku inc/datahandlers/post.php. Otwórzmy go.

Używając wbudowanej w swój edytor kodu wyszukiwarki, znajdźmy miejsca, w których są jakieś miejsca na hooki. Po prostu wyszukajmy wywołania metod run_hooks i run_hooks_by_ref. W okolicach 654 linijki znajdziemy ciąg znaków
Kod PHP:
$plugins->run_hooks_by_ref("datahandler_post_insert_post"$this); 

Po nazwie hooka (datahandler_post_insert_post) możemy wywnioskować, że jest on wywoływany w momencie dodawania posta do bazy. To chyba to, czego szukaliśmy!

W tym momencie warto wspomnieć o dwóch sposobach wywoływania hooków. Jeden, to run_hooks() - uruchamia funkcje pluginów tutaj zaczepionych bez przekazywania im żadnych argumentów. Drugi to run_hooks_by_ref(), przekazujący wybraną zmienną jako argument do funkcji obsługującej hooka. W naszym przykładzie przekazywane jest $this, czyli obiekt klasy PostDataHandler.

Dodajemy hooka do naszego pluginu. Po pierwsze, tworzymy funkcję nazwaplugina_nazwa_hooka(), pamiętając o tym, że dostajemy coś w argumencie.
Kod PHP:
function uczesie_datahandler_post_insert_post($it)
{



Następnie rejestrujemy hook. Odbywa się to przez wywołanie metody add_hook(string nazwaHooka, string nazwaFunkcjiKtoraGoObsluguje) z obiektu $plugins.

Dodajemy więc linijkę
Kod PHP:
$plugins->add_hook("datahandler_post_insert_post""uczesie_datahandler_post_insert_post"); 
Linię dodajemy gdzieś w ciągu pliku (nie w żadnej z funkcji, oczywiście). Dla porządku - umieśćmy ją nad deklaracją funkcji uczesie_info()


Mając przekazany obiekt klasy PostDataHandler, możemy z nim zrobić co się nam żywnie podoba, na przykład dopisać coś do niesionej przezeń wiadomości; ta jest przechowywana pod indeksem 'message' tablicy asocjacyjnej post_insert_data będącej polem klasy, jaką stanowi przekazany w argumencie obiekt:
Kod PHP:
function uczesie_datahandler_post_insert_post($it)
{
 
$it->post_insert_data['message'] .= "\nA ja się [b]uczę[/b]!";


Jak widać, możemy tu stosować MyCode - wiadomości są z niego parsowane w momencie wyświetlania, a nie zapisu. Funkcja przetwarzająca hook nie musi nic zwracać.

W czasie tworzenia pluginów warto posługiwać się funkcjami PHP takimi jak var_dump() czy print_r() w celu wyśledzenia sposobu zapisu danych i otwarcia sobie drogi do manipulacji nimi.

Warto pamiętać, że hook datahandler_post_insert_post jest wywoływany tylko w momencie odpowiedzi na temat; gdy wysyłany post jest pierwszym w temacie, wywołuje się datahandler_post_insert_thread_post.

Nie jesteśmy jednak ograniczeni do operowania na przekazywanych nam argumentach. Możemy bowiem wyciągnąć dla siebie zmienne, które w okolicy naszego hooka biegają, za pomocą słówka global. Mamy też możliwość wykorzystywania funkcji wbudowanych w MyBB. Dzięki temu możemy na przykład uzależnić to, czy dopiszemy coś do posta, czy nie, od liczby postów użytkownika. W tym celu zglobalizujemy sobie zmienną $post zaobserwowaną gdzieś przy 643 linijce pliku inc/datahandlers/post.php
Kod PHP:
"uid" => $post['uid'], 
Pobierzemy z niej ID piszącego (co prawda moglibyśmy je pobrać z przekazanego nam argumentu, ale dla edukacji udajmy, że o tym nie wiemy), a następnie na podstawie ID zapoznamy się z informacjami na temat użytkownika.
Kod PHP:
function uczesie_datahandler_post_insert_post($it)
{
 global 
$post// globalizacja zmiennej
 
$user get_user($post['uid']); // get_user(int IdUzykownika) to funkcja wbudowana w jadro MyBB
 
if ($user['postnum']%2$it->post_insert_data['message'] .= "\nA ja się [b]uczę[/b], w co drugim poście!"// jesli liczba postow parzysta, to dopisujemy cos do wiadomosci


7 Podsumowanie


Na koniec przypomnę, że pliki z polskimi ogonkami w MyBB należy zapisywać w kodowaniu UTF-8 bez BOM, co umożliwia na przykład edytor Notepad++.

W załączniku plik uczesie.php, który powstał w poradniku ;)