Wczoraj pisałem o dodaniu do Wego CMS wtyczek dla systemów płatności online. Cypherq poprosił o szczegóły dotyczące implementacji. Noszę się z zamiarem przygotowania kilkuetapowego howto, kiedy tylko pojawi się darmowa wersja Wego (tak, to bardzo możliwe, po szczegóły odsyłam do nbw). Póki co, o samym sposobie ładowania wtyczek.
Moduły — wtyczki z automatyczną rejestracją
Wego ma dwa rodzaje pluginów. Pierwszy rodzaj — wtyczki z automatyczną rejestracją — używany jest przez moduły. Moduł to zamknięta część systemu, widoczna jako osobna pozycja w panelu. Przykładem niech będą Artykuły
lub Kosz
.
Automatyczna rejestracja oznacza tyle, że plik z wtyczką zawiera klasę o nazwie takiej samej, jak plik i nie musi właściwie robić nic więcej:
<?php
/* $Id: foo.module.php 1 2007-04-27 12:00:00Z patrys $ */
require_once(THE_ROOT . '/class/genericModule.class.php');
/**
* Foo module
*/
class fooModule extends genericModule
{
public function __construct(& $modSys)
{
parent::__construct($modSys);
$this->module = 'foo';
}
/**
* Check if module is usable (dependencies, etc.)
*/
protected function __public_init($data)
{
return array('success' => true);
}
/**
* Get module info
*/
public function getInfo()
{
return array
(
'title' => _('Foo'),
'author' => 'patrys [ patrys at icenter pl ]',
'version' => '1.0',
'description' => _('Hello world example'),
'modified' => filemtime(__FILE__)
);
}
}
?>
Do tego dochodzi klasa dla panelu administracyjnego (dla oszczędzenia pamięci, ładowana tylko w przypadku, gdy jest to aktywny moduł w panelu):
<?php
/* $Id: foo.panel.module.php 1 2007-04-27 12:00:00Z patrys $ */
class fooPanelModule extends fooModule
{
protected function __internal_list()
{
return 'Hello world!';
}
}
?>
Jest tu kilka magicznych metod — wszystkie __public_*
dostępne są automatycznie z poziomu inych modułów i z poziomu szablonów Smarty; __internal_*
za to służą za obsługę ekranów panelu administracyjnego, wymagana jest przynajmniej obsługa metody list
, która jest domyślnym widokiem.
Inne wtyczki — ręczna rejestracja
W przypadku wtyczek pól dodatkowych
i systemów płatności okazało się, że automatyczna rejestracja nie jest najlepszym wyjściem — jedna klasa może realizować kilka funkcji, a sztuczne po niej dziedziczenie wprowadza tylko chaos w plikach. Zdecydowaliśmy się, że moduły te same muszą zgłosić obsługiwane przez siebie funkcje:
<?php
/* $Id: platnosciPayment.class.php 7234 2007-04-25 10:55:39Z patrys $ */
class platnosciPaymentType extends genericPaymentType
{
public static $paymentList = array
(
'platnosci_test' => array
(
'code' => 't',
'name' => 'Platnosci.pl (płatność testowa)',
),
'platnosci_mtransfer' => array
(
'code' => 'm',
'name' => 'Platnosci.pl - mBank mTransfer',
),
// [...]
'platnosci_credit' => array
(
'code' => 'c',
'name' => 'Platnosci.pl - Karta kredytowa',
),
);
public function getConfigData()
{
// [...]
}
public function process()
{
// [...]
}
}
$parent = paymentSystem::getInstance();
foreach (platnosciPaymentType::$paymentList as $key => $val)
$parent->register($key, 'platnosciPaymentType', $val['name']);
$parent->registerSettings('platnosci', 'platnosciPaymentType', _('Platnosci.pl'));
?>
Dzięki temu możliwa jest obsługa wszystkich sposobów zapłaty za pomocą jednej klasy (konstruktor klasy genericPaymentType
otrzymuje i zapisuje wybraną formę zapłaty).
Ładowanie wtyczek
Tutaj poszliśmy na łatwiznę:
public function loadPlugins()
{
$modDir = dir(THE_ROOT . '/payment/');
while (($file = $modDir->read()) !== false)
{
$fullPath = THE_ROOT . '/payment/' . $file;
if (!is_dir($fullPath))
{
include($fullPath);
}
}
}
Ładowanie wtyczek z automatyczną rejestracją wymaga nieco więcej zachodu (po załadowaniu pliku, trzeba jeszcze sprawdzić, czy istnieje klasa o odpowiedniej nazwie i czy dziedziczy po odpowiedniej klasie bazowej), ale samodzielna implementacja nie powinna zająć więcej niż 5 minut.
Na koniec
Po notce o zmianie firmy pojawiły się niejasne spekulacje, jakobyśmy mieli zastąpić nbw butelką wody mineralnej. Spieszę z dowodem, że młodzieniec ów żyje i ma się dobrze (a jeśli już mielibyśmy kogoś zamienić na butelkę wody, to byłby to prędzej sit0).