Zmiany w API

Nowe OPT zupełnie inaczej się inicjuje. Biblioteka nie jest w pełni samodzielna - aby ułatwić późniejszą integrację z innymi produktami serii OPL, powstał pakiet OPL zawierający podstawowe interfejsy oraz klasy. Wyekspediowana tam została m.in. obsługa konsoli debugowej oraz konfiguracji, ponadto dodaje on autoloader z prawdziwego zdarzenia. Kod OPL dołączony jest domyślnie do paczki z OPT, tak więc w dalszym stopniu wystarczy skrypt tylko rozpakować.

Aby nie być gołosłownym przedstawiam odrobinę kodu:

<?php
    // OPL Initialization
    require('../../lib/opl/base.php');
    Opl_Loader::setDirectory('../../lib/');
    Opl_Registry::setState('opl_debug_console', true);
    Opl_Registry::setState('opl_extended_errors', true);
    spl_autoload_register(array('Opl_Loader', 'autoload'));
    
    try
    {
    	$tpl = new Opt_Class;
    	$tpl->sourceDir = './templates/';
    	$tpl->compileDir = './templates_c/';
    	$tpl->charset = 'utf-8';
    	$tpl->compileMode = Opt_Class::CM_REBUILD;
    	$tpl->stripWhitespaces = false;
    	$tpl->setContentType(Opt_Class::HTML);
    	$tpl->setup();
    	
    	$tpl->assign('foo', 'Blok');
    	$tpl->parse('szablon.tpl');    
    }
    catch(Opt_Exception $exception)
    {
    	Opt_Error_Handler($exception);
    }
?>

Podstawowa inicjacja polega na załadowaniu głównego pliku biblioteki OPL, ustawieniu katalogu ze źródłami oraz autoloadera. Podany katalog musi zawierać zarówno foldery "opl", jak i "opt", gdyż inaczej nic się nam nie załaduje. Przy okazji możemy ustawić ogólne aspekty funkcjonowania wszystkich bibliotek OPL.

Jak widać, zmienione zostało nazewnictwo klas. Musiałem to zrobić, ponieważ taki zapis jest znacznie łatwiej parsować w autoloaderze, a przy okazji ucieszy fanów Zend Frameworka. Zmieniłem także nazwy niektórym metodom, np. powyżej widać, że httpHeaders() został przechrzczony na setContentType(). Jeśli zajrzymy do katalogu /lib/opt/, ujrzymy, że cały kompilator został zmodularyzowany, lecz i tak nie uchroniło to głównej klasy Opt_Compiler_Class przed zajmowaniem 65 KB na dysku twardym. Tego się już bardziej odchudzić po prostu nie da, ale możecie się pocieszać, że do tego pliku właściwie tylko ja muszę zaglądać i się w nim orientować :).

Tutaj mała uwaga: z OPT wyrzuciłem system cache. Doszedłem do wniosku, że zmuszanie tej biblioteki do zajmowania się jeszcze tym to lekkie przegięcie. Zamiast tego, pozostał bardzo prosty interfejs Opt_Cache_Hook_Interface, który należy sobie zaimplementować, aby podłączyć dowolny inny system cache. W ten sposób biblioteka łatwiej będzie integrować się z frameworkami, które często obsługują ten element we własnym zakresie. Gdyby ktoś jednak czegoś takiego nie miał, dotychczasowy kod niebawem będzie dostępny z powrotem... lecz jako osobna biblioteka, dla której jeszcze nie wymyśliłem nazwy.

Zmiany w szablonach

Szablony powinny działać bez większych problemów, aczkolwiek przy okazji przepisywania pchnąłem lekko do przodu prace nad instrukcjami. Pojawił się opt:tag, a opt:extend w pełni obsługuje już escape'owanie. Nie ma jeszcze opt:tree, opt:grid i opt:pagination, gdyż zmieniłem silnik sekcji i na razie zdążyłem go przetestować jedynie na opt:section. Sekcje są teraz o tyle fajne, że obsługują tzw. klasy uchwytów (hook classes), dzięki którym można nauczyć je obsługi dowolnego formatu danych, jaki nam się tylko zamarzy. W finalnym wydaniu nie będzie żadnych problemów, żeby sekcja potrafiła odczytywać dane np. bezpośrednio z obiektów PHP-Doctrine lub różnych elementów frameworków. Wszelkie sprawy związane z wybranym formatem są zupełnie niewidoczne po stronie szablonu:

<opt:section name="sekcja">
  .... {$sekcja.blok}
</opt:section>

Format natomiast wybieramy w skrypcie, np.

$tpl->assign('sekcja', $PDOStatement, 'PDO');

OPT zajmie się całą resztą, czyli dopasowaniem formatu do sekcji, korzystając z podanej klasy uchwytów. Klasy uchwytów mogą również modyfikować działanie zwyczajnych bloków, a twórcy instrukcji mogą korzystać z ich API w swoich produkcjach. W samych sekcjach pojawił się nowy atrybut: parent, który ułatwi tworzenie relacji. Przypomnę, że w dalszym ciągu sam fakt zagnieżdżenia jednej sekcji w innej tworzy między ich elementami relację przynależności, lecz jeśli domyślne zachowanie nam nie pasuje, możemy to zmienić:

<opt:section name="sekcja1">
   <opt:section name="sekcja2">
      <opt:section name="sekcja3" parent="sekcja1">
         ....
      </opt:section>
   </opt:section>
</opt:section>

Teraz elementy sekcji3 są przyłączone do sekcji1, a nie sekcji2. Ponadto, niedawno na forum Nowaker zaproponował, aby OPT zgodnie z logiką obsługiwał następujący blok sekcji: {$sekcja.blok.elementTablicy}. Wola jego stała się faktem i teraz OPT skanuje cały taki blok w poszukiwaniu nazwy dowolnej aktywnej obecnie sekcji.

Z innych nowości należy wymienić możliwość przypisania bloku do konkretnego szablonu. Dostęp jest realizowany poprzez $this.blok.

Dokumentacja

Spędziłem niedawno dużo czasu nad dokumentacją do OPT 2, a przede wszystkim nad przekonwertowaniem dotychczasowych wyczynów na TypeFriendly. Efekt jest następujący:

  1. Na ukończeniu jest opis składni szablonów. Jedynie dwie instrukcje nie posiadają jeszcze dokumentacji i trochę funkcji.
  2. Opisana jest większość API biblioteki.
  3. Opisane są wszystkie aktualnie wykorzystywane i zatwierdzone dyrektywy konfiguracyjne.
  4. Na ukończeniu są strony opisujące migrację z: PHP, OPT 1.x oraz Smarty'ego. Szczególnie w OPT 1.1.x ludzie się krzywili na ostatni z wymienionych opisów, że głupoty opisuje, zamiast konkretów. Teraz się poprawiłem i różnica jakościowo-ilościowa powinna być widoczna gołym okiem.

Dokumentacja dołączona jest do paczki, jest także możliwość przejrzenia jej on-line: on-line. Można także zapoznać się z zalążkiem angielskiej dokumentacji do OPL.

Zakończenie

Wykaz paczek można znaleźć tutaj. Na kolejną niestety znów przyjdzie trochę poczekać. W sobotę wyjeżdżam na tydzień, a zaraz później pochłonie mnie przeprowadzka do Krakowa i egzamin na uczelni, tak więc będę "wolny" dopiero za jakiś miesiąc. W tym czasie będę wrzucać jakieś mniejsze rzeczy na SVN i tam też będzie najświeższa wersja. Z drugiej strony, eXtreme już coś tam kombinuje z Open Power Classes, a konkretniej jego klasą "Opc_Paginator" do stronicowania. Myślę, że również Radzio w końcu zrobi swoje API dla Google Charts.

Na koniec należy uczciwie zaznaczyć, że OPT 2.0.0-dev7 przeszedł z LGPL 3 na zmodyfikowaną licencję BSD, co Wam ułatwi później dodawanie go do projektów komercyjnych, a wszystkim utrudni życie z przyjmowaniem zewnętrznych patchów i poprawek. Licencja LGPL była o tyle fajna, że z definicji obejmowała sobą również wszystkie poprawki i patche. Zmodyfikowana BSD tak nie robi i będę musiał odmawiać ich dodania do SVN bez podpisanego papierka ze zgodą na wydanie ich na podanej licencji, tak jak to robi Zend ze swoim Frameworkiem. Coś za coś.