<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://blog.invenzzia.org/pl/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>Invenzzia... po polsku</title>
  <link>http://blog.invenzzia.org/pl/</link>
  <description></description>
  <language>pl</language>
  <pubDate>nie, 24 sie 2008 10:38:38 +0200</pubDate>
  <copyright>Copyright &amp;copy; Invenzzia</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>OPT 2.0.0-dev7</title>
    <link>http://blog.invenzzia.org/pl/post/OPT-200-dev7</link>
    <guid isPermaLink="false">urn:md5:b131a991b46030d10b663233a603ff4b</guid>
    <pubDate>śro, 20 sie 2008 11:31:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>development</category><category>dokumentacja</category><category>opt2</category><category>releases</category>    
    <description>&lt;p&gt;3 miesiące i 10 dni. Tyle zajęło przepisywanie dotychczasowego kodu OPT do nowej, lepszej wersji. Dziś w końcu uznałem, że dotarł on do punktu, w którym może aspirować do miana &quot;dev7&quot; i odpowiednia paczka znalazła się w działach &quot;Download&quot;. Zmian jest sporo, głównie związanych z API biblioteki, którą teraz się nieco inaczej inicjuje. Poprawiłem też nieco kompilator, dodając do szablonów parę nowych możliwości oraz znacząco rozbudowałem dokumentację, która zresztą dołączona jest do wydania.&lt;/p&gt;    &lt;h2&gt;Zmiany w API&lt;/h2&gt;


&lt;p&gt;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ć.&lt;/p&gt;


&lt;p&gt;Aby nie być gołosłownym przedstawiam odrobinę kodu:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;&amp;lt;?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-&amp;gt;sourceDir = './templates/';
    	$tpl-&amp;gt;compileDir = './templates_c/';
    	$tpl-&amp;gt;charset = 'utf-8';
    	$tpl-&amp;gt;compileMode = Opt_Class::CM_REBUILD;
    	$tpl-&amp;gt;stripWhitespaces = false;
    	$tpl-&amp;gt;setContentType(Opt_Class::HTML);
    	$tpl-&amp;gt;setup();
    	
    	$tpl-&amp;gt;assign('foo', 'Blok');
    	$tpl-&amp;gt;parse('szablon.tpl');    
    }
    catch(Opt_Exception $exception)
    {
    	Opt_Error_Handler($exception);
    }
?&amp;gt;
&lt;/pre&gt;


&lt;p&gt;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 &quot;opl&quot;, jak i &quot;opt&quot;, gdyż inaczej nic się nam nie załaduje. Przy okazji możemy ustawić ogólne aspekty funkcjonowania wszystkich bibliotek OPL.&lt;/p&gt;


&lt;p&gt;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 &lt;code&gt;httpHeaders()&lt;/code&gt; został przechrzczony na &lt;code&gt;setContentType()&lt;/code&gt;. Jeśli zajrzymy do katalogu &lt;code&gt;/lib/opt/&lt;/code&gt;, ujrzymy, że cały kompilator został zmodularyzowany, lecz i tak nie uchroniło to głównej klasy &lt;code&gt;Opt_Compiler_Class&lt;/code&gt; 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ć :).&lt;/p&gt;


&lt;p&gt;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 &lt;code&gt;Opt_Cache_Hook_Interface&lt;/code&gt;, 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.&lt;/p&gt;


&lt;h2&gt;Zmiany w szablonach&lt;/h2&gt;


&lt;p&gt;Szablony powinny działać bez większych problemów, aczkolwiek przy okazji przepisywania pchnąłem lekko do przodu prace nad instrukcjami. Pojawił się &lt;code&gt;opt:tag&lt;/code&gt;, a &lt;code&gt;opt:extend&lt;/code&gt; w pełni obsługuje już escape'owanie. Nie ma jeszcze &lt;code&gt;opt:tree&lt;/code&gt;, &lt;code&gt;opt:grid&lt;/code&gt; i &lt;code&gt;opt:pagination&lt;/code&gt;, gdyż zmieniłem silnik sekcji i na razie zdążyłem go przetestować jedynie na &lt;code&gt;opt:section&lt;/code&gt;. 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:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;opt:section name=&amp;quot;sekcja&amp;quot;&amp;gt;
  .... {$sekcja.blok}
&amp;lt;/opt:section&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Format natomiast wybieramy w skrypcie, np.&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$tpl-&amp;gt;assign('sekcja', $PDOStatement, 'PDO');
&lt;/pre&gt;


&lt;p&gt;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: &lt;code&gt;parent&lt;/code&gt;, 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ć:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;opt:section name=&amp;quot;sekcja1&amp;quot;&amp;gt;
   &amp;lt;opt:section name=&amp;quot;sekcja2&amp;quot;&amp;gt;
      &amp;lt;opt:section name=&amp;quot;sekcja3&amp;quot; parent=&amp;quot;sekcja1&amp;quot;&amp;gt;
         ....
      &amp;lt;/opt:section&amp;gt;
   &amp;lt;/opt:section&amp;gt;
&amp;lt;/opt:section&amp;gt;
&lt;/pre&gt;


&lt;p&gt;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: &lt;code&gt;{$sekcja.blok.elementTablicy}&lt;/code&gt;. Wola jego stała się faktem i teraz OPT skanuje cały taki blok w poszukiwaniu nazwy dowolnej aktywnej obecnie sekcji.&lt;/p&gt;


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


&lt;h2&gt;Dokumentacja&lt;/h2&gt;


&lt;p&gt;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:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Na ukończeniu jest opis składni szablonów. Jedynie dwie instrukcje nie posiadają jeszcze dokumentacji i trochę funkcji.&lt;/li&gt;
&lt;li&gt;Opisana jest większość API biblioteki.&lt;/li&gt;
&lt;li&gt;Opisane są wszystkie aktualnie wykorzystywane i zatwierdzone dyrektywy konfiguracyjne.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dokumentacja dołączona jest do paczki, jest także możliwość przejrzenia jej on-line: &lt;a href=&quot;http://www.invenzzia.org/docs/opt2-pl/&quot; hreflang=&quot;pl&quot;&gt;on-line&lt;/a&gt;. Można także zapoznać się z zalążkiem angielskiej dokumentacji do &lt;a href=&quot;http://www.invenzzia.org/docs/opl2-en/&quot; hreflang=&quot;en&quot;&gt;OPL&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;Zakończenie&lt;/h2&gt;


&lt;p&gt;Wykaz paczek można znaleźć &lt;a href=&quot;http://libs.invenzzia.org/pl/download&quot; hreflang=&quot;pl&quot;&gt;tutaj&lt;/a&gt;. 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ę &quot;wolny&quot; 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ą &quot;Opc_Paginator&quot; do stronicowania. Myślę, że również Radzio w końcu zrobi swoje API dla Google Charts.&lt;/p&gt;


&lt;p&gt;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ś.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/OPT-200-dev7#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/OPT-200-dev7#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/34</wfw:commentRss>
      </item>
    
  <item>
    <title>OPT zbiera się do kupy</title>
    <link>http://blog.invenzzia.org/pl/post/OPT-zbiera-si-do-kupy</link>
    <guid isPermaLink="false">urn:md5:c0240785fe81bd52320a5b247080535d</guid>
    <pubDate>pią, 25 lip 2008 19:13:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>development</category><category>OPT2</category><category>optymalizacja</category>    
    <description>&lt;p&gt;Mija trzeci miesiąc, odkąd na tym blogu pojawiły się ostatnie wieści dotyczące Open Power Template'a 2.0.0. Czas ten nie był stracony, gdyż (pomijając sesję na uczelni) upłynął na ostrym przepisywaniu całego projektu. Wieści nie było, gdyż doprowadzenie nowego kodu do stanu uruchamialności nieco trwało, ale w końcu jest. Kompilator na nowo kompiluje szablony, i to już bez użycia rekurencji, zmory poprzednich wydań nawet, jeśli po części spowodowana ona była przez błąd w samym PHP :). Ale do rzeczy...&lt;/p&gt;    &lt;p&gt;Począwszy od dev7, OPT będzie niekompatybilny wstecz z wydaniami dev1 do dev6, ale tylko od strony API. Zmiany w sumie nie są wielkie i dotyczą bardziej mechanizmu inicjowania biblioteki. Załączam przykładowy kod:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;&amp;lt;?php 
    // OPL Initialization 
    require('../../lib/opl/base.php'); 
    Opl_Base::setDirectory('../../lib/'); 
    Opl_Base::setDebugMode(Opl_Base::DEBUG_ERROR); 
    spl_autoload_register(array('Opl_Base', 'autoload')); 
     
    try 
    { 
    	$tpl = new Opt_Class; 
    	$tpl-&amp;gt;sourceDir = './templates/'; 
    	$tpl-&amp;gt;compileDir = './templates_c/'; 
    	$tpl-&amp;gt;charset = 'utf-8'; 
    	$tpl-&amp;gt;compileMode = Opt_Class::CM_REBUILD; 
    	$tpl-&amp;gt;stripWhitespaces = false; 
    	$tpl-&amp;gt;httpHeaders(Opt_Class::HTML); 
    	$tpl-&amp;gt;setup(); 
    	 
    	$tpl-&amp;gt;assign('foo', 'I am a value.'); 
    	$tpl-&amp;gt;parse('test_parser_1.tpl');     
    } 
    catch(Opl_Exception $exception) 
    { 
    	Opl_Error_Handler($exception); 
    } 
?&amp;gt; 
&lt;/pre&gt;


&lt;p&gt;Jak widać, inny jest mechanizm inicjalizacji. Biblioteki doczekały się wspólnego rdzenia, autoloadera, lepszej hermetyzacji, lecz trzeba uczciwie zaznaczyć, że lekko odbije się to na wydajności. Cena postępu - albo przypakowana i zap***jąca jak gepard biblioteka, albo zwinniejsza lecz nieco wolniejsza antylopa GNU. Dokładniej, mamy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Autoloader&lt;/li&gt;
&lt;li&gt;Mechanizm rejestrowania obiektów (coś na wzór Zend_Registry)&lt;/li&gt;
&lt;li&gt;Tryb debugowania, w tym ujednolicona konsola debugowa. Jeśli ktoś będzie korzystać z np. 5 bibliotek OPL i włączy sobie takową, nie będzie mu wyskakiwać 5 pop-upów, tylko jeden zbiorczy.&lt;/li&gt;
&lt;li&gt;Ujednolicone mechanizmy konfiguracji&lt;/li&gt;
&lt;li&gt;Grupa wspólnych interfejsów: zasoby, cache, system tłumaczeń.&lt;/li&gt;
&lt;li&gt;Obsługa błędów, w pełni wykorzystująca możliwości systemu wyjątków.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Zmianie uległ system nazewnictwa klas, teraz jest on bardzo podobny do tego, co widzimy w Zend Framework. Różnice dotyczą drobnych szczegółów umożliwiających pakowanie kilku klas do jednego pliku i obsługę takich sytuacji przez autoloader. Wiadomo na pewno, że zmieni się sposób obsługi interfejsu tłumaczeń. Wiem, że co najmniej jedna inna biblioteka także będzie go wykorzystywać, dlatego uznałem, że zamiast rejestrować obiekt odpowiedniej klasy w każdym projekcie z osobna, wykorzystam do tego rdzeń OPL:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;Opl_Base::register('opl_translate', new MojaKlasaTlumaczen); 
&lt;/pre&gt;


&lt;p&gt;Wielu z Was z pewnością interesuje, co w tej chwili potrafi nowy kod OPT. Do jakiegokolwiek sensownego wykorzystania nie nadaje się on dalej, chociażby z tego powodu, że nie zaimplementowałem na nowo jeszcze żadnej instrukcji. Tak naprawdę dopiero przedwczoraj udało mi się skompilować pierwszy szablon, zaś dzisiaj dostrajałem kompilator wyrażeń po jego przeróbce na wersję nierekurencyjną. Zostało mu tylko 9 z 98 testów do zaliczenia i dotyczą one w zasadzie odwracania kolejności argumentów w funkcji oraz detekcji niektórych błędów składni związanych z nawiasami. Czyli takie techniczne duperele, które można naprawić w pół godziny przy dobrych wiatrach. Przepisywanie kompilatora poszłoby znacznie szybciej, ale postanowiłem, że skoro już przepisuję wszystko, pozbędę się do końca rekurencji. I dopiąłem swego, opanowując do perfekcji iteracyjną wersję przeszukiwania drzewa w głąb, hehehe. OPT nie jest już wrażliwy na głębokość jakiegokolwiek drzewa i na komunikat &quot;Nesting level too deep&quot; trzeba sobie zasłużyć zbyt pazernym własnym skryptem.&lt;/p&gt;


&lt;p&gt;Kod wraz z polską dokumentacją API kompilatora jest do ściągnięcia z repozytorium SVN. Trzymajcie kciuki za dev7...&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/OPT-zbiera-si-do-kupy#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/OPT-zbiera-si-do-kupy#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/33</wfw:commentRss>
      </item>
    
  <item>
    <title>TypeFriendly 0.1.0 wydane</title>
    <link>http://blog.invenzzia.org/pl/post/TypeFriendly-010-wydane</link>
    <guid isPermaLink="false">urn:md5:150b7aad27160b6c415d7dc7bf5f53e9</guid>
    <pubDate>śro, 23 lip 2008 10:29:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>TypeFriendly</category>
        <category>development</category><category>releases</category><category>typefriendly</category>    
    <description>&lt;p&gt;W końcu zakończyliśmy tłumaczenie dokumentacji na język angielski i gotowy od kilkunastu dni kod wreszcie został wydany jako pierwsza wersja systemu generowania dokumentacji TypeFriendly. Można ją pobrać w dziale &lt;a href=&quot;http://www.invenzzia.org/pl/pliki&quot; hreflang=&quot;pl&quot;&gt;Pliki&lt;/a&gt; na stronie głównej. Dokumentacja dostarczana jest w wersji źródłowej i robi jednocześnie za przykład, dlatego nie obawiajcie się, że czegoś brakuje. Wszystkie informacje potrzebne do zbudowania HTML-owej wersji dokumentacji znajdują się w pliku &lt;code&gt;/info/README.txt&lt;/code&gt; - jest to kwestia wklepania jednego polecenia z konsoli. Trwają już prace nad nową stroną Invenzzii i znajdzie się tam miejsce na dokumentację on-line.&lt;/p&gt;    &lt;p&gt;O TypeFriendly pisałem dokładniej w poprzednim wpisie i tam znajdziecie więcej informacji. Tutaj dodam tylko, że eXtreme odwalił kawał świetnej roboty, wyczerpująco opisując po polsku &lt;strong&gt;całą składnię Markdown z dziesiątkami przykładów&lt;/strong&gt;. Z pewnością opis ten przyda się wielu osobom.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/TypeFriendly-010-wydane#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/TypeFriendly-010-wydane#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/31</wfw:commentRss>
      </item>
    
  <item>
    <title>TypeFriendly</title>
    <link>http://blog.invenzzia.org/pl/post/TypeFriendly</link>
    <guid isPermaLink="false">urn:md5:759da236043100759dab1375858eff8f</guid>
    <pubDate>śro, 02 lip 2008 20:51:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>TypeFriendly</category>
        <category>development</category><category>dokumentacja</category><category>typefriendly</category>    
    <description>&lt;p&gt;Z eXtremem ciężko pracujemy, by pierwsza wersja ujrzała w końcu światło dzienne i jesteśmy już bardzo blisko. W związku z tym chciałbym bliżej przedstawić ten projekt, który z pewnością powinni docenić inni programiści, autorzy rozmaitych skryptów i poszukujących sensownego narzędzia do generowania dokumentacji. Pomysł na napisanie TypeFriendly zrodził się w mojej głowie po nieudanych zmaganiach z dodaniem paru niezbędnych rzeczy do parsera XSLT dla DocBook. Widać choćby po dokumentacji PHP, co można z tym zrobić (kolorowanie składni, wiele różnych formatów, ogromna ilość pomocnych znaczników), ale nie dajmy się zwariować. To są wręcz tygodnie siedzenia, by osiągnąć podobny efekt. Pomijam już fakt, że byłby on słabo przenośny... wolałem poświęcić te tygodnie na stworzenie czegoś bardziej przydatnego.&lt;/p&gt;    &lt;p&gt;TypeFriendly jest więc systemem generowania dokumentacji, ale innego pokroju niż np. phpDocumentor, który skanuje kod źródłowy Twojego projektu i robi opisy do wszystkich napotkanych klas i funkcji. Tutaj rozdziały piszemy sami od A do Z i sami układamy je w żądanym porządku, podobnie jak w DocBooku. Na tym podobieństwa się kończą, ponieważ TF z definicji zawiera już wszystko, co potrzeba, a został tak zaprojektowany, by dokumentację pisało się intuicyjnie.&lt;/p&gt;


&lt;p&gt;Cechy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;W TF dokumentację tworzymy, pisząc tekst w zwykłych plikach tekstowych, korzystając ze składni Markdown. Dodatkowo, na początku umieszczamy różne dodatkowe tagi, dzięki którym możemy ustawić tytuł, informacje o wersji czy np. listę &quot;Zobacz także&quot;.&lt;/li&gt;
&lt;li&gt;TF automatycznie układa nasze pliki w rozdziały na podstawie ich nazwy i sortuje alfabetycznie. Jednak zawsze możemy wprowadzić własny układ - w pliku &quot;ze wskazówkami do sortowania&quot; definiujemy własną kolejność. To, czego tam nie zapisaliśmy, pozostanie alfabetycznie.&lt;/li&gt;
&lt;li&gt;TF posiada wbudowaną opcję kolorowania składni kodu źródłowego.&lt;/li&gt;
&lt;li&gt;TF samodzielnie generuje pełną nawigację pomiędzy rozdziałami, podobnie jak spis treści.&lt;/li&gt;
&lt;li&gt;TF jest zaprojektowany do rozwijania dokumentacji w kilku językach. Posiada nie tylko możliwość przetłumaczenia tekstów interfejsu, ale także proste narzędzie do sprawdzania aktualności &quot;pochodnych wersji językowych&quot;.&lt;/li&gt;
&lt;li&gt;TF umożliwia wygenerowanie wyjściowej dokumentacji w formacie XHTML (w wersji z wieloma podstronami lub na jednej). Przygotowujemy też specjalny format umożliwiający szybki import dokumentacji do bazy danych i udostępnienie np. możliwości jej komentowania on-line.&lt;/li&gt;
&lt;li&gt;TF oprawia dokumentację w bardzo ładną szatę graficzną, którą możecie podziwiać np. w dokumentacji do OPTv2 (robionej właśnie w TF).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Wprawdzie wydania żadnego jeszcze nie było, ale chętni mogą już teraz połączyć się z naszym nowym SVN-em i ściągnąć projekt stamtąd. Link do polecenia &lt;em&gt;checkout&lt;/em&gt; jest następujący: &lt;em&gt;http://svn.invenzzia.org/svn/typefriendly/trunk/&lt;/em&gt; - serdecznie zachęcam już teraz do testów. W repozytorium jest plik README oraz będąca już na ukończeniu dokumentacja w języku polskim.&lt;/p&gt;


&lt;p&gt;Żeby nie być gołosłownym, pokażę co ciekawsze opcje na przykładzie paru fragmentów. Pierwszym z nich będzie jeden z plików manuala OPTv2 (library.optnode.txt):&lt;/p&gt;

&lt;pre&gt;
Title: Klasa optNode
ShortTitle: optNode
Status: abstract
Extends: library.optcodebuffer
ExtendedBy:
 - library.optscannable
 - library.optcharacterdata
 - library.optexpression

----
Abstrakcyjna klasa węzła. Zapewnia obsługę podstawowych własności, jak rodzic i typ.

Pola klasy
----------
Wszystkie pola klasy są chronione.

 Nazwa         | Typ       | Opis
---------------|-----------|---------------------------------------
 $type         | Integer   | Numeryczny identyfikator typu.
 $parent       | optNode   | Rodzic węzła.

Dostępne identyfikatory typów:

1. `OPT_CDATA_NODE` - `optCharacterData`
2. `OPT_TEXT_NODE` - `optText`
3. `OPT_EXPRESSION_NODE` - `optExpression`
4. `OPT_ELEMENT_NODE` - `optElement`
5. `OPT_ROOT_NODE` - `optRoot`
&lt;/pre&gt;


&lt;p&gt;Na początku pliku znajduje się nagłówek, w którym umieszczamy tzw. tagi. Tam właśnie określany jest właściwy tytuł, a w tym wypadku również zależności między klasami. Zauważmy, że do innych klas odwołujemy się, podając identyfikatory rozdziałów, które je opisują. Oczywiście każdy z tych &quot;obiektowych&quot; tagów posiada także wersję, gdzie nazwy możemy wpisać bezpośrednio (np. gdybyśmy dziedziczyli po klasie wbudowanej w PHP). Dostępnych tagów jest więcej. Przykładowo, można bardzo łatwo zrobić listę &quot;Zobacz także&quot;, która wygląda mniej więcej tak:&lt;/p&gt;

&lt;pre&gt;
SeeAlso:
 - chapter.text1
 - chapter.text2
 - chapter.text3
&lt;/pre&gt;


&lt;p&gt;Gdy lista tagów dobiegnie końca, przechodzimy do właściwej treści pisanej w formacie &lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot; hreflang=&quot;pl&quot;&gt;Markdown&lt;/a&gt;. Autor zaprojektował go bazując na formatowaniu używanym powszechnie w rozmaitych plikach tekstowych czy e-mailach (można powiedzieć, że napisał parser do składni, która sama wyewoluowała :)). Tekst źródłowy jest przez to niesamowicie czytelny i na dobrą sprawę czyta się go niewiele gorzej, niż gdyby był faktycznie sformatowany. Trochę gorzej, gdy ktoś jest przyzwyczajony już do jakiejś składni wiki, bo MD nie zawsze takowe wiki przypomina (zwróćcie uwagę chociażby na sposób wykonania tabelki). Jednak można się dość łatwo przyzwyczaić - w Markdownie klepiemy również teksty na naszą stronę i muszę powiedzieć, że jest to całkiem przyjemne narzędzie, które z pewnością ujrzycie w niejednym produkcie Invenzzii. Jedyny mankament jest taki, że oficjalny parser obsługuje tylko jeden słuszny format - XHTML. O LaTeXu czy innych na razie trzeba niestety zapomnieć, ale na to już ostrzymy sobie zęby :).&lt;/p&gt;


&lt;p&gt;Najgorszy problem przy tworzeniu dokumentacji to nawigacja. Linki &quot;Poprzedni/Następny/W górę&quot; załatwia TypeFriendly, sekcję &quot;Zobacz także&quot; robimy za pomocą znaczników, a co z klikalnymi nazwami funkcji i klas? Myślałem nad tym i wymyśliłem rozwiązanie genialne w swej prostocie. W dodatkowym pliku tekstowym definiujemy kawałki tekstów, które mają zostać zamienione na odnośnik. Przykładowo, wpisujemy tam, że &lt;code&gt;`optClass::parse()`&lt;/code&gt; ma, oprócz nadania mu standardowego formatowania, zostać zmienione na odnośnik do &lt;em&gt;library.optclass.parse&lt;/em&gt; i już się niczym więcej przejmować nie musimy. Niestety, do takich przeróbek Markdowna jeszcze nie doszliśmy i pierwsza wersja tego bajeru nie będzie jeszcze zawierać. Wszystko w swoim czasie.&lt;/p&gt;


&lt;p&gt;TypeFriendly obsługiwany jest w całości z konsoli systemu operacyjnego. Testowaliśmy go na Linuksie i Windowsie - w obu systemach działa póki co bez zarzutów. Do działania potrzebny jest wyłącznie interpreter PHP. W połączeniu z intuicyjną składnią oraz wbudowanym wsparciem dla wielojęzyczności powinno to zachęcić wielu ludzi do pomocy przy tłumaczeniach, rozwoju oryginalnej wersji, a nawet tworzeniu nowych wyjść. Przetworzenie naszych plików na XHTML to kwestia wklepania jednego polecenia:&lt;/p&gt;

&lt;pre&gt;
php ./typefriendly.php -l pl -o xhtml ./sciezka/do/dokumentacji/
&lt;/pre&gt;


&lt;p&gt;Porównajmy to z DocBookiem - sam format jest nieco bardziej rozwlekły, ale stosunkowo łatwy do opanowania. Do konwersji jednak potrzeba trochę więcej narzędzi - DTD, sam zestaw DocBok XSL Stylesheet i wreszcie sam parser XSLT. Jego wybór jest nie bez znaczenia, gdyż ze zwykłym, szybkim i łatwym w użyciu xsltproc nie dostaniemy np. kolorowania składni. Użytkownicy Windowsa natomiast mają kompletnie prze.... jeśli autor projektu dodatkowo zrobi na DocBooku framework do budowania dokumentacji, w którym część narzędzi napisana jest w... Bashu. Nie trzeba takich kwiatków daleko szukać - jak myślicie, co odpowiada za dokumentację PHP? :) Z chęcią bym do niej coś popisał, gdyby choć raz udało mi się uruchomić ichniejszy framework i cokolwiek przetworzyć.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/TypeFriendly#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/TypeFriendly#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/29</wfw:commentRss>
      </item>
    
  <item>
    <title>SVN uruchomiony</title>
    <link>http://blog.invenzzia.org/pl/post/SVN-uruchomiony</link>
    <guid isPermaLink="false">urn:md5:b069e5e0e7b55faeecfa3fd56ebdc85a</guid>
    <pubDate>pon, 30 cze 2008 08:08:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Invenzzia</category>
        <category>development</category><category>svn</category>    
    <description>    &lt;p&gt;Niestety porządna konfiguracja systemu kontroli wersji na naszym serwerze nie jest tak łatwa i przyjemna, jak na Sourceforge.net, aczkolwiek w końcu znalazłem czas i pomysł, jak to wykonać. Repozytorium działa pod adresem http://svn.invenzzia.org/ z tym, że nie została jeszcze zainstalowana żadna porządna jego przeglądarka. W ciągu dnia wrzucę tam aktualny kod przebudowywanych Open Power Libs oraz bliskie ukończenia pierwszej wersji 0.1.0 TypeFriendly do tworzenia dokumentacji, zaś wszystkie informacje odnośnie połączenia znajdą się na stronie głównej.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/SVN-uruchomiony#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/SVN-uruchomiony#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/27</wfw:commentRss>
      </item>
    
  <item>
    <title>OPT 2.0.0-dev6</title>
    <link>http://blog.invenzzia.org/pl/post/OPT-200-dev6</link>
    <guid isPermaLink="false">urn:md5:e3094cab72537f268ece4f7353879f33</guid>
    <pubDate>sob, 10 maj 2008 14:15:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>development</category><category>dokumentacja</category><category>opt2</category>    
    <description>&lt;p&gt;Do ściągnięcia dostępna jest wreszcie kolejna wersja rozwojowa OPT. Jej zawartość opisałem w poprzednim wpisie, dlatego tu dodam tylko, że wbrew zapowiedziom, nie ma jeszcze instrukcji &lt;code&gt;opt:grid&lt;/code&gt; z powodów, które zaraz wyjaśnię. Ponadto nie da się jeszcze ustawiać statusu escape'owania dla pojedynczego szablonu, ale takowy z globalnej konfiguracji i ustawień wyrażenia w klamerkach już działa ładnie. Za to dodałem implementację instrukcji &lt;code&gt;opt:capture&lt;/code&gt; i częściową &lt;code&gt;opt:cycle&lt;/code&gt;. Polskich użytkowników z pewnością ucieszy informacja, że podczas długiego weekendu doprowadziłem do względnego porządku nasz nowy system dokumentowania TypeFriendly i OPT 2 ma już nową, ładną dokumentację :)&lt;/p&gt;    &lt;p&gt;Dostałem niedawno parę pytań, czy można już powoli zacząć używać OPT 2 w rzeczywistych projektach. Odpowiadałem, że większość rzeczy już jest gotowa i w nich raczej zmian nie będzie, aczkolwiek nic nie gwarantuję. W kolejnym devie okaże się, że dobrze zrobiłem, nic nie gwarantując, ponieważ OPT wymaga paru drastycznych zmian.&lt;/p&gt;


&lt;h2&gt;Sekcje&lt;/h2&gt;


&lt;p&gt;Od strony szablonu wszystko zostaje po staremu, za to zmieni się trochę interfejs skryptowy. W OPT już od pewnego czasu istnieją elementy pozwalające uniezależnić szablony od interfejsów skryptu, dzięki czemu zmiany w silniku nie muszą iść w parze z przepisywaniem wszystkich szablonów, co jest bolączką innych parserów (w tym Smarty'ego, gdzie na forach widziałem już takie cudaczne konstrukcje, że aż głowa może rozboleć). Sekcje już od dawna stanowiły jedną z nich, gdyż skrywały sposób łączenia sekcji podrzędnych i nadrzędnych, a także zawierały obsługę generowania danych &quot;w locie&quot; oraz alternatywny format tablic. Wszystko to było jednak zakodowane na sztywno w kodzie, a dodanie doń czegoś nowego jest kłopotliwe. Przecież formaty danych mogą być jeszcze inne, stąd pomysł, by wprowadzić modularyzację samych sekcji. Instrukcja jako taka zapewnia wyłącznie szkielet podpinający wszystko, gdzie trzeba w drzewku XML. My natomiast za pomocą pluginów możemy łatwo nauczyć sekcję, żeby np. pobierała dane np. bezpośrednio z PHP-Doctrine czy też iterowała po obiekcie :). Zastosowanie:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;opt:section name=&amp;quot;foo&amp;quot;&amp;gt;
 {$foo.bar}
&amp;lt;/opt:section&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Nie musimy się już martwić, czy element &lt;code&gt;foo&lt;/code&gt; jest obiektem, a my odwołujemy się do pola &quot;bar&quot;, czy też tablicą. Po stronie szablonu &lt;code&gt;foo.bar&lt;/code&gt; oznacza blok &quot;bar&quot; w elemencie &quot;foo&quot;, natomiast zadaniem skryptu jest nadanie mu jakiegoś konkretnego znaczenia (tablica, obiekt itd.). Analogicznie, nie obchodzi nas również budowa danych dla sekcji jako takiej - czy to jest sekcja dynamiczna, czy tablica w jakimś formacie, czy też obiekt... Wszystko będzie można łatwo zaprogramować.&lt;/p&gt;


&lt;p&gt;Po stronie skryptu pojawi się metoda w stylu &lt;em&gt;setSectionType&lt;/em&gt; służąca do określenia, jak OPT powinien przetworzyć daną sekcję:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$tpl -&amp;gt; setSectionType('foo', 'mojPluginObiektowy');
$tpl -&amp;gt; assign('foo', new obiektPoKtorymMoznaIterowac);
&lt;/pre&gt;


&lt;p&gt;Gdy nie określiliśmy typu, OPT wybierze standardową postać tablicową.&lt;/p&gt;


&lt;p&gt;Zalety:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Po stronie szablonu już nas kompletnie nic nie obchodzi. Sekcje możemy kopiować metodą Ctrl+C, a one bez zmiany jednego znaku w pełni dostosują się do sytuacji w nowym szablonie bez naszej ingerencji.&lt;/li&gt;
&lt;li&gt;Koniec narzekań, czemu sekcje nie obsługują czegośtam, albo że format jest debilny :)&lt;/li&gt;
&lt;li&gt;Jednolita kontrola obsługi po stronie skryptu.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Modularyzacja kompilatora&lt;/h2&gt;


&lt;p&gt;Kompilator zostanie rozbity na większą ilość mniejszych plików, gdyż jest on ładowany raz na jakiś czas i zyski ze zbicia wszystkiego w dwa mega-pliki są znikome. Wpływ na skrypty korzystające z OPT powinien być zerowy.&lt;/p&gt;


&lt;h2&gt;Zmiany w obsłudze błędów&lt;/h2&gt;


&lt;p&gt;Niebawem pojawi się Open Power Classes 1.0.0-dev1, a w planach są też inne projekty. Jeśli ma to być coś więcej, niż tylko zbiór bibliotek o podobnej nazwie, trzeba ujednolicić niektóre elementy. Oczywiście wspólną częścią jest obsługa błędów - każda z bibliotek musi więc zawierać taki sam plik z odpowiednim współdzielonym kodem, który może być używany przez wszystkie z nich jednocześnie. Jeżeli poza przechwytywaniem wyjątku optException i kierowaniem go do &lt;code&gt;optErrorHandler()&lt;/code&gt; nie robisz z nim nic więcej, wtedy zmiana nie powinna Cię dotknąć.&lt;/p&gt;


&lt;h4&gt;Poprawa hermetyzacji klasy głównej!!&lt;/h4&gt;


&lt;p&gt;Rzecz musi zostać ujednolicona, żeby nie powstała kolejna niedorzeczność pod postacią &quot;dlaczego jedne dane są chronione, choć potrzebuje ich kompilator, a inne nie&quot;. Jeśli odwoływałeś się wyłącznie do pól konfiguracyjnych, zmiana nie powinna Cię dotknąć.&lt;/p&gt;


&lt;h2&gt;Nowa dokumentacja&lt;/h2&gt;


&lt;p&gt;Jak pisałem, wreszcie OPT 2 posiada nową, zapowiadaną jakiś czas temu dokumentację. Za jej generowanie odpowiada napisany w PHP silnik TypeFriendly obsługujący m.in. kolorowanie składni. Zostanie on wydany na licencji GNU GPL, gdy tylko uporządkuję trochę jego kod i napiszę dokumentację pokazującą, jak z niego korzystać. Tak czy inaczej jego obecność pozwoli nawet na takie bajery, jak wersja on-line dokumentacji z komentarzami użytkowników.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/OPT-200-dev6#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/OPT-200-dev6#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/26</wfw:commentRss>
      </item>
    
  <item>
    <title>Co nowego w OPT</title>
    <link>http://blog.invenzzia.org/pl/post/Co-nowego-w-OPT</link>
    <guid isPermaLink="false">urn:md5:4836080a510835be9e024045bcef96b6</guid>
    <pubDate>nie, 27 kwi 2008 13:06:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>development</category><category>opt2</category>    
    <description>&lt;p&gt;Minęło już trochę czasu od ostatnich wieści z frontu, dlatego naprawiam zaległości. Za jakiś tydzień pojawi się kolejna wersja developerska. Prace posunęły się jeszcze dalej do przodu. Obejmują one zaimplementowanie kolejnych &quot;brakujących&quot; elementów, a także (co powinno niektórych ucieszyć) - zmniejszanie zużycia zasobów serwera w trakcie kompilacji. Zobaczmy zatem, z czym będziemy mieli do czynienia.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;Pochodne sekcji&lt;/strong&gt;&lt;/p&gt;


&lt;p&gt;Nowe pochodne sekcji: &lt;code&gt;opt:tree&lt;/code&gt; oraz &lt;code&gt;opt:grid&lt;/code&gt;. Pierwszą z nich znamy już z OPT 1 i służy do renderowania drzew. Zmianie uległa jej składnia, ponieważ na nowym kompilatorze nie da się tak beztrosko szlachtać HTML-a, nie domykając znaczników. Z drugiej strony wymusiło to wprowadzenie bardziej czytelnego formatu. Popatrzmy na to:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;  &amp;lt;opt:tree name=&amp;quot;mytree&amp;quot;&amp;gt;
  	&amp;lt;opt:list&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;opt:content/&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;/opt:list&amp;gt;
  	&amp;lt;opt:node&amp;gt;&amp;lt;li&amp;gt;{$mytree.title} &amp;lt;opt:content /&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/opt:node&amp;gt;  
  &amp;lt;/opt:tree&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Czyli innymi słowy - definiujemy wygląd listy, definiujemy wygląd węzła i mówimy, w którym miejscu mogą się one zagnieżdżać. Algorytm przetwarzania takiego drzewa, jaki OPT wstawia do skompilowanego szablonu, opiera się na pewnej sztuczce, ale jest skuteczny. Oczywiście format danych jest taki sam, jak w poprzednich wersjach - do danych sekcji musimy dołączyć pole &quot;depth&quot; z głębokością elementu.&lt;/p&gt;


&lt;p&gt;Całkowitą nowość stanowi &lt;code&gt;opt:grid&lt;/code&gt;. Jego działanie opiszę na przykładzie. Z pewnością każdy widział internetowe galerie zdjęć. Miniaturki są tam ułożone w tabelce, np. po 5 w jednym wierszu. Rzadko się zdarza, by liczba elementów była wielokrotnością tejże piątki, dlatego przeważnie część ostatniego wiersza będzie pusta. Można to rozwiązać za pomocą CSS-a (sposób podał niedawno na naszym forum eXtreme), lecz czasem po prostu trzeba narysować rzeczywistą tabelę. Sam algorytm opiera się na sprawdzaniu reszty z dzielenia indeksu, ale &lt;em&gt;dlaczego ma się tym w ogóle zajmować szablon?&lt;/em&gt; Zgodnie z filozofią OPT, powinniśmy przecież mówić tylko, co chcemy zrobić, a nie instruować krok po kroku - JAK. Stąd też instrukcja &lt;code&gt;opt:grid&lt;/code&gt;:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;table&amp;gt;
&amp;lt;opt:grid name=&amp;quot;tabelka&amp;quot; cols=&amp;quot;3&amp;quot;&amp;gt;
 &amp;lt;tr&amp;gt;
  &amp;lt;opt:item&amp;gt;
   &amp;lt;td&amp;gt;&amp;lt;img parse:src=&amp;quot;$tabelka.zdjecie&amp;quot;/&amp;gt;&amp;lt;/td&amp;gt;
  &amp;lt;/opt:item&amp;gt;
  &amp;lt;opt:emptyItem&amp;gt;
   &amp;lt;td&amp;gt;&amp;amp;nbsp;&amp;lt;/td&amp;gt;
  &amp;lt;/opt:emptyItem&amp;gt; 
 &amp;lt;/tr&amp;gt;
&amp;lt;/opt:grid&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Instrukcją obejmujemy cały wiersz, a w nim dodatkowo zaznaczamy, jak mają się wyświetlać poszczególne komórki. Mamy tu dwa warianty. &lt;code&gt;opt:item&lt;/code&gt; mówi, jak wygląda komórka z danymi, zaś &lt;code&gt;opt:emptyItem&lt;/code&gt; - jak komórka bez danych. Wprawieniem tego w ruch zajmuje się OPT. Instrukcja gridu przyjmuje identyczny format danych, jak zwykła sekcja.&lt;/p&gt;


&lt;p&gt;Skoro przy sekcjach jesteśmy, zmienia się składnia wywołań z &quot;else&quot; w nazwie. Dotąd były to znaczniki bez treści, wizualnie rozdzielając zawartość rodzica na dwie części. Okazało się jednak, że z paru powodów muszę zrezygnować z takiego zapisu na rzecz następującej konstrukcji:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;opt:section name=&amp;quot;foo&amp;quot;&amp;gt;
  Tutaj treść sekcji

  &amp;lt;opt:sectionelse&amp;gt;
      Tutaj to, co się dzieje, gdy lista jest pusta.
  &amp;lt;/opt:sectionelse&amp;gt;

&amp;lt;/opt:section&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Miejsce umieszczenia tego znacznika jest teraz bez znaczenia - OPT sam sobie go przesunie tam, gdzie trzeba, żeby wygenerowany z tego kod PHP miał sens.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Automatyczne escape'owanie&lt;/strong&gt;
OPT 1 w ogóle nie zajmował się escape'owaniem danych ze skryptu podczas ich wyświetlania. Zmianę jakościową wprowadzi teraz OPT 2, zaś twórca szablonów będzie mieć nad tym procesem pełną kontrolę. Założenia są następujące:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Wszystko, co próbujemy wyświetlić we wnętrzu atrybutu XML, musi być escape'owane przez &lt;em&gt;htmlspecialchars()&lt;/em&gt; i od tego nie ma &quot;zlituj&quot; w trybie XML.&lt;/li&gt;
&lt;li&gt;Wyrażenia w klamerkach domyślnie także są escape'owane, lecz nad tym procesem programista ma kontrolę. Status escape'owania może być zdefiniowany globalnie w konfiguracji OPT, w głównym znaczniku szablonu (jego zasięg obejmie wtedy tylko aktualny szablon) lub też pojedyncze wyrażenie za pomocą dwóch modyfikatorów &lt;em&gt;e&lt;/em&gt; lub &lt;em&gt;u&lt;/em&gt; wstawionych na jego początek. Przykłady: &lt;code&gt;{e:$blok}&lt;/code&gt; oraz &lt;code&gt;{u:$blok}&lt;/code&gt;. Oczywiście działa to inteligentnie, tzn. jeśli włączyliśmy escape'owanie globalnie, dodanie modyfikatora nie spowoduje, że blok zostanie przetrawiony dwukrotnie. Dostępna będzie również specjalna funkcja &lt;em&gt;esc()&lt;/em&gt; pozwalająca na escape'owanie tylko konkretnego elementu wyrażenia.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;System językowy&lt;/strong&gt;
OPT 2 zawiera zmieniony interfejs do integracji z systemem językowym, lecz dotąd nie był on w ogóle nigdzie przez kod wykorzystywany. Obsługa pojawi się w najnowszym devie, w składni identycznej, jak w OPT 1.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;System stronicowania&lt;/strong&gt;
Zmianom uległ także interfejs integracji z systemem stronicowania oraz po części składnia instrukcji &lt;code&gt;opt:pagesystem&lt;/code&gt;. W tej chwili szczegóły jeszcze dopracowujemy. Obie te rzeczy pojawiają się teraz dlatego, gdyż równolegle z OPT 2.0.0-dev6 ukaże się pierwsza wersja developerska nowego projektu o nazwie &lt;em&gt;Open Power Classes&lt;/em&gt;. Jest to zbiór niewielkich klas o różnych zadaniach, które są zbyt małe, by je pakować i szumie ogłaszać jako kolejne projekty (każdy projekt Open Power XXX musi posiadać unikalny kod literowy, a ilość liter w alfabecie jest niestety ograniczona :)). Na dzień dobry znajdą się tam dwie klasy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;opcPagination&lt;/code&gt; - system stronicowania kompatybilny z OPT autorstwa eXtreme'a.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;opcCharts&lt;/code&gt; - API dla Google Charts stworzone przez Radzia&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;W późniejszych wersjach dojdzie jeszcze m.in. system językowy.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Optymalizacje&lt;/strong&gt;
Optymalizacji jest kilka:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Zużycie pamięci. Polega ono na wyszukiwaniu miejsc, w którym skrypt mógłby zwalniać pamięć i obiekty, ale jednak tego nie robi. W kompilatorze rezygnuję również z domyślnej inicjacji pustych tablic, gdyż każda taka struktura to strata rzędu przynajmniej 400 bajtów, a często nie są one potrzebne.&lt;/li&gt;
&lt;li&gt;Głębokość rekurencji - jakiś czas temu pisałem o zbyt szybkim zjadaniu stosu przez OPT z powodu użycia rekurencyjnego algorytmu przetwarzania węzłów drzewa. W OPT 1 nie było z tym problemu, gdyż węzłami były jedynie instrukcje, zaś tutaj domagał się tego każdy znacznik HTML. Wdrożyłem dlatego algorytm hybrydowy, który robi rekurencyjne wywołanie tylko wtedy, gdy faktycznie jest ono do czegoś potrzebne, zaś w przeciwnym wypadku wykorzystuje mechanizm kolejki u jednego z już pracujących przetwarzaczy. W praktyce każdy znacznik, który nie jest bezpośrednio obsługiwany przez OPT, przetwarzany jest teraz w ten sposób, dzięki czemu oszczędzamy stos. Również niektóre instrukcje mogą tak pracować.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Inne&lt;/strong&gt;
Nowy dev będzie zawierać także trochę pomniejszych poprawek. Zacząłem w końcu tworzyć zestaw testów dla poszczególnych instrukcji, dzięki czemu jestem w stanie sprawdzić zachowanie biblioteki dla znacznie większej liczby możliwych kombinacji i wychwycić rozmaite kretyńskie zachowania.&lt;/p&gt;


&lt;p&gt;PS. Pewnie niektórzy zauważyli, że mój blog zniknął z sieci. Informuję, że niebawem zostanie on przywrócony pod dotychczasowym adresem, zatem bez obaw.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Co-nowego-w-OPT#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Co-nowego-w-OPT#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/25</wfw:commentRss>
      </item>
    
  <item>
    <title>Wymagania OPT</title>
    <link>http://blog.invenzzia.org/pl/post/Wymagania-OPT</link>
    <guid isPermaLink="false">urn:md5:d0e794006c5d5f0728882df9a161f559</guid>
    <pubDate>sob, 05 kwi 2008 09:32:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>development</category><category>OPT2</category><category>optymalizacja</category>    
    <description>&lt;p&gt;Na bugtrackerze pojawiło się ostatnio zgłoszenie informujące o błędzie &quot;Nesting level too deep - recursive dependency&quot; przy próbie uruchomienia jednego z przykładów w najnowszej wersji rozwojowej OPTv2. Po dokładniejszych oględzinach wyszło na jaw, że winny jest zbyt wyśrubowany limit ustawiony w konfiguracji PHP przez autora zgłoszenia (ponad czterokrotnie mniejszy, niż wartość domyślna). Jednak przy tej okazji myślę, że warto trochę bardziej przyjrzeć się temu, jakie wymagania postawi nowy OPT interpreterowi i wyjaśnić kilka spraw z tym związanych.&lt;/p&gt;    &lt;p&gt;Optymalizacje, jakie implementuję w OPT, dotyczą przede wszystkim głównej klasy parsera oraz kompilatora. Pierwsza z nich, jako część kodu ładowana każdorazowo, ma narzucone bardzo wyśrubowane wymagania. Nie ma tutaj wyszukanych algorytmów, dlatego przyspieszanie działania dotyczy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zmniejszania objętości kodu.&lt;/li&gt;
&lt;li&gt;Minimalizacji odwołań do dysku twardego.&lt;/li&gt;
&lt;li&gt;Wykorzystaniem najwydajniejszych elementów języka.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chodzi o to, aby załadowanie biblioteki było jak najmniej obciążające dla interpretera, a w konsekwencji używającego ją skryptu.&lt;/p&gt;


&lt;p&gt;Nieco inaczej sprawa wygląda z kompilatorem, który ładowany jest tylko okazjonalnie, zatem może być obszerny i rozbity na więcej składowych (aczkolwiek bez zbędnej przesady). Tutaj kluczową rolę zaczynają odgrywać limity ustawione w konfiguracji PHP, gdyż przy szczególnie złych wiatrach może się zdarzyć, że kompilator zużyje wszystkie dostępne zasoby. Niestety, powiększona funkcjonalność kosztuje, a skoro użytkownicy pragnęli mieć parsowanie także XML-owych znaczników, muszą liczyć się z tym, że dla każdego z nich trzeba teraz tworzyć obiekt węzła i dla każdego z nich trzeba wykonać trochę prac przygotowawczych. Moją rolą jest tutaj uczynienie tego zużycia tak małego, jak to tylko jest możliwe.&lt;/p&gt;


&lt;p&gt;Elementy, które mogą się wyczerpać podczas używania kompilatora to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stos&lt;/li&gt;
&lt;li&gt;Pamięć operacyjna&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wykorzystywane algorytmy, z racji operowania na strukturze zwanej drzewem, korzystają dość mocno z rekurencji, przez co liczba aktualnie wykonywanych funkcji i metod szybko rośnie. W PHP domyślnym limitem narzuconym na głębokość rekurencji jest 64 i do pracy z OPT najlepiej zostawić go na takim poziomie, a już na pewno nie bawić się w jego zmniejszanie do jakichś śmiesznych wartości pokroju &quot;16&quot;, co zresztą zaszkodziłoby nie tylko OPT, ale i wielu innym skryptom :). Każdą rekurencję można jednak zastąpić iteracyjną wersją, która może i nie zużywa mniej pamięci, ale przynajmniej jest niezależna od wspomnianego limitu. Odpowiednie przeróbki wprowadzone są już teraz do wielu metod, które zamiast wywoływać się rekurencyjnie, korzystają np. z kolejek. Najgorzej sprawa wygląda z dwoma algorytmami:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Przetwarzanie drzewa przez procesory instrukcji&lt;/li&gt;
&lt;li&gt;Kompilacja wyrażeń&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;W pierwszym z nich mamy następującą sytuację: odnajdujemy węzeł jakiejś instrukcji i musimy go przetworzyć. Kierujemy go więc do odpowiedniego procesora (klasa pochodna od &lt;code&gt;optInstruction&lt;/code&gt;), on generuje do niej kod PHP i decyduje, co zrobić z dziećmi danego węzła. Zazwyczaj decyduje się na ich obróbkę. Tu wkracza wywołanie rekurencyjne i cały proces powtarza się od początku. Trudności to rozrzucenie całego algorytmu po mnóstwie klas, które mogą być na dokładkę oficjalnie rozbudowywane przez zainteresowanych programistów. Co więcej, niektóre instrukcje wymagają, aby przetwarzanie rozpoczęło się natychmiast wraz z wywołaniem metody przetwarzającej, ponieważ od tego, jaki kod PHP wygenerują sobie potomkowie, zależy dalsza obróbka ich rodzica. Eliminuje to w oczywisty sposób kolejkę. Stworzenie eleganckiego zamiennika byłoby proste, gdybyśmy mieli dostęp do programowania niskopoziomowego, lecz tak nie jest.&lt;/p&gt;


&lt;p&gt;Popatrzmy, jak to wpłynie na kompilację. Mamy jakiś rozbudowany szablon, w którym znaczniki zagnieżdżone są aż do głębokości 30. Sam OPT z kompilatorem może w porywach zużyć dodatkowe 10 zagnieżdżeń, zaś w najgłębszym miejscu jest na dokładkę jeszcze skomplikowane wyrażenie z nawiasami. Zatem całość zużyje ok. 45 wywołań, z dostępnych 64, czyli ponad 70% limitu! I choć przypadek jest dość pesymistyczny, bo prawdę mówiąc mi się nigdy nie zdarzyło, żebym musiał robić jakiś plik HTML z 30-ma zagnieżdżonymi znacznikami, to jednak pokazuje on, że kompilacja to proces wymagający.&lt;/p&gt;


&lt;p&gt;Skoro bez brzydkich sztuczek, które nie spodobałyby się na pewno twórcom instrukcji, nie da się usunąć rekurencji, to jak sobie z tym poradzić? Wpadłem na pomysł, gdzie rekurencji nie usuwamy, lecz za to drastycznie ją ograniczamy. Korzystam tutaj z faktu, że natychmiastowy dostęp do tego, co wykompilowały dzieci, jest potrzebny tylko kilku instrukcjom, natomiast np. zwyczajnym znacznikom XML/HTML jest to po grzyba, gdyż one i tak nie wiedzą, co z tym zrobić. Mamy więc sporą szansę, że gdy wybierzemy losowy węzeł z drzewa, trafimy na taki, któremu rekurencja jest niepotrzebna. Dlaczego więc nie zaproponować dwóch wersji algorytmu: imperatywnej i rekurencyjnej, w zależności od potrzeb? Tam, gdzie instrukcje robią czary, mogą sobie zażyczyć prawdziwej rekurencji, natomiast normalnie wszystko idzie poprzez kolejki. Wtedy przy dobrych wiatrach, takie drzewo o głębokości 30, może być przetworzone na jeden raz, bez żadnej rekurencji! W normalnych warunkach natomiast zejdzie ona na głębokość 3, 4, co jest już akceptowalne.&lt;/p&gt;


&lt;p&gt;Druga sprawa dotyczy zużycia pamięci. Wprawdzie nie jest tu aż tak tragicznie, ale da się zauważyć wyraźne zwiększenie zapotrzebowania w porównaniu z kompilatorem do OPT 1.x, nawet pomimo wykorzystania patentów z tamtego projektu. Większość tego zajmuje oczywiście samo drzewo. Mierzyłem ostatnio zużycie pamięci generowane przez pojedyncze obiekty węzłów i wyniki wahały się w granicach 2 kilobajtów na pusty obiekt bez udziwnień, natomiast przy dodaniu atrybutu, rosło średnio o kilobajt. Gdy instrukcje zaczną dopisywać do buforów kod PHP, sprawa się pogarsza, ale dotyczy to tylko wybranych węzłów w całym szablonie. Okazuje się, że możemy tu trochę zaoszczędzić. Obiekty wykorzystują kilka tablic, które dotąd były automatycznie inicjowane na samym początku, na przykład:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;abstract class optScannable extends optNode implements Iterator
{
	protected $subnodes = array();
&lt;/pre&gt;


&lt;p&gt;W większości węzłów część tych tablic stoi pusta, więc nie ma sensu, aby były one cały czas stworzone. Poprawiłem kod tak, aby odpowiednie metody tworzyły pustą tablicę dopiero, gdy będzie ona potrzebna, zaś z deklaracji wywaliłem dopiski &lt;code&gt;= array()&lt;/code&gt;. Dało to ciekawy efekt: na jednej tak wywalonej tablicy zacząłem oszczędzać 400 bajtów. Nowe rezultaty pomiarów są następujące:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Węzeł bez atrybutów: 1400 b.&lt;/li&gt;
&lt;li&gt;Węzeł z jednym atrybutem: 2350 b.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dodatkowa oszczędność może zostać osiągnięta dzięki pamiętaniu o kasacji niepotrzebnych już danych o dużej objętości, jak np. treść szablonu.&lt;/p&gt;


&lt;p&gt;O czym należy pamiętać, korzystając z nowego OPT, jeśli chodzi o kwestie wydajnościowe:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Z wyśrubowanymi limitami kompilator na pewno będzie się wysypywać. Myślę, że 16 MB pamięci dla skryptu (aktualny domyślny limit) to wartość na tyle rozsądna, by kompilator mógł odwalić dobrą robotę nawet z całkiem rozbudowanym szablonem oraz jednocześnie aby zostało coś dla skryptu.&lt;/li&gt;
&lt;li&gt;Parsowanie szablonu najlepiej uruchamiać na końcu, kasując przedtem w skrypcie niepotrzebne już dane o dużej objętości.&lt;/li&gt;
&lt;li&gt;Kompilacja szablonów z dziedziczeniem może wymagać więcej pamięci, szczególnie przy nadpisywaniu już istniejących snippetów (parser musi trzymać w pamięci również nadpisane wersje).&lt;/li&gt;
&lt;li&gt;Niezaimplementowany jeszcze tryb tekstowy (quirks mode) wymagać będzie znacznie mniej pamięci dzięki uproszczonemu drzewu (brak znaczników XML).&lt;/li&gt;
&lt;li&gt;Kompilacja uruchamiana jest raz na długi czas; podczas normalnej pracy można spokojnie zapomnieć o istnieniu tych wszystkich wymagań.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Myślę, że ten wpis dość dobrze pokazuje, o ilu aspektach trzeba pamiętać, pisząc porządną bibliotekę. Klucz to wiedzieć, na ile można sobie w danym miejscu pozwolić i że oprócz biblioteki, gdzieś tam ma jeszcze w tej samej pamięci, w tej samej płaszczyźnie pracować wykorzystujący ją skrypt, który także ma swoje wymagania.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Wymagania-OPT#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Wymagania-OPT#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/23</wfw:commentRss>
      </item>
    
  <item>
    <title>OPT 1.1.4</title>
    <link>http://blog.invenzzia.org/pl/post/OPT-114</link>
    <guid isPermaLink="false">urn:md5:4b3f8313708632936a1a407ccb88a9bc</guid>
    <pubDate>nie, 30 mar 2008 14:02:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>nowe wersje</category><category>OPT</category>    
    <description>&lt;p&gt;Wypuściłem dziś w świat ostatnią stabilną wersję Open Power Template'a z gałęzi 1.x. Powinna ona mieć już wszystko, co potrzebne jest użytkownikom tej wersji. Poprawiłem znalezione błędy oraz dodałem kilka nowych opcji, o które byłem proszony. Gdyby oczywiście wykryty został jakiś krytyczny błąd uniemożliwiający komuś pracę, przygotuję dla niego odpowiednią poprawkę, ale poza tym żadnych działań więcej nie przewiduję w tym zakresie. Wszystko przez to, że przyszłością jest OPT 2.0.0.&lt;/p&gt;    &lt;p&gt;Epopeja OPT w listopadzie będzie obchodzić czwarte urodziny istnienia. Stabilne wydania dostępne są już od 19 miesięcy. Do sukcesów odniesionych w tym czasie zaliczyłbym:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Stworzenie czegoś, co może śmiało konkurować ze Smarty'm i w wielu aspektach prześcignąć tamten parser.&lt;/li&gt;
&lt;li&gt;Osiągnięcie (przynajmniej w Polsce) całkiem niezłej popularności. Choć na forach dalej królują posty dotyczące Smarty'ego, ale jeśli już trafi się coś innego, najczęściej jest to OPT. Biblioteka istnieje w świadomości polskich programistów i doczekała się nawet - uwaga uwaga - wejścia do programu nauczania niektórych uczelni wyższych. Dowiedziałem się niedawno od znajomego, że w krakowskiej Wyższej Szkole Zarządzania i Bankowości OPT jest w programie do przedmiotu &quot;Techniki internetowe&quot;. A ponieważ wykłada tam wielu pracowników AGH, jest szansa, że za dwa lata sam będę miał okazję tych wykładów posłuchać :D.&lt;/li&gt;
&lt;li&gt;Zdobycie nowych doświadczeń. Próba stworzenia bez nich OPT 2.0.0 zakończyłaby się pewnie spektakularną klapą.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Oczywiście były też i kiepskie elementy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Nie czarujmy się, w OPT 1.x jest kilka improwizacji i nie do końca przemyślanych lub rozwiniętych rozwiązań. Dziś mam kaca moralnego po lekko spieprzonej obsłudze buforowania wyjścia czy niewykorzystaniu od początku prawdziwego potencjału instrukcji &lt;em&gt;bind&lt;/em&gt; oraz &lt;em&gt;insert&lt;/em&gt; - przecież dodać do tego jeszcze nowy mechanizm detekcji, który szablon uległ modyfikacji i mielibyśmy dziedziczenie szablonów, jak w mordę strzelił jeszcze zanim w światku PHP ten termin w ogóle zaistniał :).&lt;/li&gt;
&lt;li&gt;Baza wiedzy o OPT. Kompletna dokumentacja jest tylko po angielsku, zaś jedyne trzy artykuły, które znam, są po polsku i w dodatku mojego autorstwa.&lt;/li&gt;
&lt;li&gt;Źle zorganizowane zaplecze internetowe oraz społecznościowe.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Te trzy rzeczy chcę poprawić w nowym kodzie, nieobciążany już żadnymi głupotami w stylu wstecznej kompatybilności. Pierwsze porady zostały opublikowane, na dysku mam zaczętych kilka artykułów, powstaje dedykowany system dokumentacji, a ponadto mamy wreszcie zalążek porządnej infrastruktury sieciowej.&lt;/p&gt;


&lt;p&gt;Zaś wracając do samego OPT 1.1.4. Z poprawek błędów najważniejsze są chyba dwie. Odkryłem, że opcja &quot;default&quot; z instrukcji &quot;include&quot; nie działała poprawnie przy włączonej opcji &lt;strong&gt;performance&lt;/strong&gt;. Powodem było pomylenie nazw zmiennych. Druga rzecz dotyczy odkrycia, że choć w kodzie PHP było przygotowane wszystko do obsługi bloków konfiguracyjnych... zapomniałem podłączyć je pod parser wyrażeń :D. Do dziś nie wiem, jak to się stało, a tym bardziej jakim cudem nikt się nie zorientował (pewnie nikt nie korzysta z tego i tyle :)). Oprócz poprawek błędów, dorzuciłem parę nowych opcji. Na prośbę jednego z użytkowników dodałem możliwość ustawienia prefiksu skompilowanym szablonom tak, aby nie zachodziły kolizje nazw plików (znana ze Smarty'ego opcja &lt;strong&gt;compileId&lt;/strong&gt;). Do parsera wyrażeń dodałem obsługę wartości specjalnych &lt;strong&gt;true&lt;/strong&gt;, &lt;strong&gt;false&lt;/strong&gt; oraz &lt;strong&gt;null&lt;/strong&gt;, których jakimś cudem także nie było. Pojawiły się dwa nowe wyłączniki pozwalające wyłączyć niektóre elementy składni (bloki konfiguracyjne oraz dostęp do zmiennych środowiskowych). Ponadto dostałem informacje, że zestaw funkcji w OPT 1.x był wzięty trochę z kosmosu, dlatego przeportowałem kilka użytecznych funkcji z wersji 2.0.0. Są to: &lt;code&gt;escape()&lt;/code&gt;, &lt;code&gt;firstof()&lt;/code&gt;, &lt;code&gt;strip()&lt;/code&gt;, &lt;code&gt;indent()&lt;/code&gt;, &lt;code&gt;spacify()&lt;/code&gt; i &lt;code&gt;truncate()&lt;/code&gt;. Na koniec wymienione zostały informacje copyright w związku z przeniesieniem projektu na grupę Invenzzia. Zapraszam do ściągania.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/OPT-114#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/OPT-114#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/22</wfw:commentRss>
      </item>
    
  <item>
    <title>OPT 2.0.0-dev5</title>
    <link>http://blog.invenzzia.org/pl/post/OPT-200-dev5</link>
    <guid isPermaLink="false">urn:md5:7470fd5526a958ad88c9f3399bb23080</guid>
    <pubDate>czw, 20 mar 2008 14:27:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>development</category><category>komponenty</category><category>OPT2</category>    
    <description>&lt;p&gt;Upłynęło trochę więcej czasu, niż planowałem, od ostatniej wersji dev, lecz poniekąd w ramach rekompensaty dodałem do OPT sporą liczbę nowych rzeczy. Rozwiązanie sprawy DTD, prologów XML, obsługi sekcji CDATA i escape'owania kodu, dokończenie parsera wyrażeń czy wreszcie pełna implementacja komponentów są moim zdaniem znaczącym krokiem naprzód. Do końca prac jest już bliżej, niż dalej. Na zakodowanie czeka już tylko kilka instrukcji, prawie wszystkie pozostałe są już ukończone. Kompilator działa bardzo dobrze, na ukończeniu jest cały interfejs programistyczny, przechodząc ostatnie szlify. Niebawem planuję rozpocząć pierwsze testy bojowe na bazie mojej własnej strony domowej, a także rozpocząć tworzenie biblioteki Open Power Forms zgodnej z nową wersją.&lt;/p&gt;    &lt;p&gt;Nowy Open Power Template posiada całkowicie zmieniony mechanizm komponentów, który jest teraz znacznie bardziej elastyczny i pozwala na uzyskiwanie wielu ciekawych efektów niewielkim kosztem. Fundamentalne zasady działania pozostały, zmieniła się cała reszta. Oto przykładowa próbka pokazująca, jak teraz będzie wyglądać praca z formularzami budowanymi na bazie komponentów:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;opt:snippet name=&amp;quot;componentView&amp;quot;&amp;gt;
  &amp;lt;com:div class=&amp;quot;field&amp;quot; invalid=&amp;quot;field error&amp;quot;&amp;gt;
    &amp;lt;p&amp;gt;{$opt.component.title}: &amp;lt;opt:display /&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p class=&amp;quot;desc&amp;quot; opt:if=&amp;quot;$opt.component.description&amp;quot;&amp;gt;{$opt.component.description}&amp;lt;/p&amp;gt;
    &amp;lt;opt:onEvent name=&amp;quot;error&amp;quot; message=&amp;quot;info&amp;quot;&amp;gt;
      &amp;lt;p class=&amp;quot;error&amp;quot;&amp;gt;{@info}&amp;lt;/p&amp;gt;
    &amp;lt;/opt:onEvent&amp;gt;
  &amp;lt;/com:div&amp;gt;
&amp;lt;/opt:snippet&amp;gt;

&amp;lt;div class=&amp;quot;form&amp;quot;&amp;gt;
&amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;skrypt.php&amp;quot;&amp;gt;

&amp;lt;opt:input name=&amp;quot;imie&amp;quot; template=&amp;quot;componentView&amp;quot;&amp;gt;
   &amp;lt;opt:set name=&amp;quot;title&amp;quot; str:value=&amp;quot;Podaj swoje imię&amp;quot; /&amp;gt;
   &amp;lt;opt:set name=&amp;quot;description&amp;quot; str:value=&amp;quot;Przynajmniej 3 litery&amp;quot; /&amp;gt;
&amp;lt;/opt:input&amp;gt;

&amp;lt;opt:input name=&amp;quot;nazwisko&amp;quot; template=&amp;quot;componentView&amp;quot;&amp;gt;
   &amp;lt;opt:set name=&amp;quot;title&amp;quot; str:value=&amp;quot;Podaj swoje nazwisko&amp;quot; /&amp;gt;
   &amp;lt;opt:set name=&amp;quot;description&amp;quot; str:value=&amp;quot;Przynajmniej 3 litery&amp;quot; /&amp;gt;
&amp;lt;/opt:input&amp;gt;

&amp;lt;opt:input name=&amp;quot;wiek&amp;quot; template=&amp;quot;componentView&amp;quot;&amp;gt;
   &amp;lt;opt:set name=&amp;quot;title&amp;quot; str:value=&amp;quot;Podaj swój wiek&amp;quot; /&amp;gt;
   &amp;lt;opt:set name=&amp;quot;description&amp;quot; str:value=&amp;quot;Przedział: 10-99 lat&amp;quot; /&amp;gt;
&amp;lt;/opt:input&amp;gt;

&amp;lt;div class=&amp;quot;foot&amp;quot;&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Wyślij&amp;quot; /&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Nowa implementacja w pełni wykorzystuje możliwości, jakie stwarza instrukcja &lt;code&gt;opt:snippet&lt;/code&gt; oraz dziedziczenie szablonów. Gdyby ktoś chciał, mógłby zaprogramować obiekty komponentów w ten sposób, że zbędne stanie się nawet ręczne podawanie opisów poszczególnych pól. Komponent może obsługiwać zdarzenia, wyświetlanie samego siebie oraz swojego otoczenia, zarządzać parametrami, a nawet ingerować w atrybuty wybranych znaczników HTML (do tego służy przestrzeń nazw &lt;code&gt;com&lt;/code&gt;). OPT sam z siebie zawierać będzie jedynie mechanizm, lecz nie będzie w nim ani jednego gotowego komponentu (poza przykładami, ale te nie są bezpośrednio częścią biblioteki). Po prostu aby w pełni wykorzystać cały potencjał, klasy komponentów powinny być zintegrowane z systemami kontroli formularzy, obsługą błędów, systemem językowym itd., a to wykracza daleko poza dziedzinę biblioteki. Gotową do natychmiastowego użycia implementacją komponentów będzie Open Power Forms.&lt;/p&gt;


&lt;p&gt;Niestety, w nowym devie lekko zawalona jest sprawa z dokumentacją. Po prostu TypeFriendly jeszcze specjalnie nie potrafi generować tego, co chcemy, a DocBookowej wersji nie rozwijałem, pisząc już wszystko w nowym formacie. Dlatego mam nadzieję, że nikomu nie stanie się krzywda, gdy zobaczy... zbiór źródłowych plików TXT, które trzeba przeglądać narzędziami notatnikopodobnymi :). Na pocieszenie dodam, że składnia Markdowna Extra jest bardzo czytelna dla człowieka (w sumie zaprojektowano ją właśnie na wzór &quot;formatowań&quot; stosowanych właśnie w e-mailach, plikach README itd.), dlatego poza brakiem nawigacji oraz kolorów nie powinno to być aż takie trudne w lekturze. Trzeba jedynie pamiętać o ustawieniu (na wszelki wypadek) uniksowych zejść do nowej linii i kodowania UTF-8.&lt;/p&gt;


&lt;p&gt;Wraz z publikacją nowej wersji, zamieściłem też na stronie bibliotek pierwszą partię oficjalnych, praktycznych porad do OPT. Oto linki do najważniejszych miejsc:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://libs.invenzzia.org/pl/download&quot; hreflang=&quot;pl&quot;&gt;Download&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://libs.invenzzia.org/pl/porady/open-power-template&quot; hreflang=&quot;pl&quot;&gt;Porady&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/OPT-200-dev5#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/OPT-200-dev5#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/20</wfw:commentRss>
      </item>
    
  <item>
    <title>Dokumentacje</title>
    <link>http://blog.invenzzia.org/pl/post/Dokumentacje</link>
    <guid isPermaLink="false">urn:md5:3b67fd8596bd156bd1177cb95c3aaf94</guid>
    <pubDate>sob, 08 mar 2008 22:29:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>dokumentacja</category>    
    <description>&lt;p&gt;Jak dotąd, wszystkie dokumentacje tworzymy w pakiecie bazującym na DocBooku (dodanych kilka drobnych znaczników), z których wersja HTML-owa tworzona jest arkuszami XSLT. Istniejące systemy przetwarzania automatycznie dbają o utworzenie nawigacji między rozdziałami oraz podział tego na pojedyncze pliki, o ile wybraliśmy taki tryb. Niestety, utworzenie kompletnego frameworka dla dokumentacji jest okropnie skomplikowane, co tłumaczy fakt, dlaczego całość zapisana jest póki co w jednym wielkim pliku XML, a przykłady nie mają kolorowania składni. Do tego dochodzi problem z parserami XSLT. Choć w DocBooku piszę od dawna, postanowiłem znaleźć alternatywne rozwiązanie i rozpocząć projekt gotowego do użycia generatora dokumentacji napisanego w PHP i korzystającego z prostszej składni. eXtreme ochrzcił go mianem TypeFriendly.&lt;/p&gt;    &lt;p&gt;Ogólna zasada działania nie zmieni się. Na wejście podajemy zbiór plików źródłowych dokumentacji i otrzymujemy przetworzone dokumenty HTML. Jest jednak szereg zmian w stosunku do DocBooka:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Z definicji zakładamy, że dokumentacja złożona jest z wielu plików. TypeFriendly na podstawie nazwy pliku ustala zależności między poszczególnymi rozdziałami, a tam, gdzie nie chcemy mieć alfabetycznego porządku, możemy zdefiniować własny w osobnym pliku.&lt;/li&gt;
&lt;li&gt;Poszczególne pliki korzystać będą z bardzo wygodnej składni Markdown, lekko rozszerzonej pod kątem tworzenia dokumentacji. Dodatkowo jeżeli podamy parserowi listę stałych, metod, funkcji itd., będzie on mógł automatycznie zamieniać występujące w tekście odwołania do nich na odnośniki do stosownych rozdziałów. Na początku każdego dokumentu możliwe będzie umieszczenie kilku informacji o pliku, np.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;
Title: Tytuł strony
Author: Zyx
Tags: dokumentacja
SeeAlso: library.class-x.foo
-----
Witamy w dokumentacji
=====================
To jest krótka dokumentacja napisana w Markdownie.
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;Trzy tryby wyświetlania: XHTML (jedna strona), XHTML (wiele stron), wersja on-line. Dwie pierwsze wersje to generatory dokumentacji do lektury w trybie offline, podobnie jak np. aktualny manual OPT. W trzeciej, TypeFriendly utworzy zbiór zserializowanych tablic z informacjami o wszystkich podstronach. Dowolny skrypt PHP może je szybko wczytać i umieścić np. w bazie danych strony WWW tak, aby umożliwić szybką budowę dokumentacji on-line, z komentarzami użytkowników, wyszukiwarką oraz innymi bajerkami. W każdym trybie będzie istnieć kolorowanie składni identyczne z tym używanym na blogu.&lt;/li&gt;
&lt;li&gt;Obsługa wielu języków.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Przekonwertowałem już część dokumentacji OPT na nowy format i pisze się w nim wygodnie. Kodowanie samego TypeFriendly rozpocząłem natomiast dziś rano. Istnieje już szkielet aplikacji oraz parsery niezbędnych formatów plików. Niedługo będzie można obejrzeć to publicznie. Skrypt będzie aplikacją czysto konsolową, odpalaną z linii komend. Działać ma zarówno w systemach uniksowych, jak i pod Windowsem.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Dokumentacje#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Dokumentacje#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/19</wfw:commentRss>
      </item>
    
  <item>
    <title>OPT 2.0.0-dev4</title>
    <link>http://blog.invenzzia.org/pl/post/OPT-200-dev4</link>
    <guid isPermaLink="false">urn:md5:6305be4ea0eddac6cb766e2d3fd21899</guid>
    <pubDate>nie, 02 mar 2008 11:14:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>development</category><category>dziedziczenie</category><category>OPT2</category>    
    <description>&lt;p&gt;Do ściągnięcia jest już czwarta wersja developerska Open Power Template'a. Projekt zaczyna nabierać kształtów, jako że na ukończeniu jest już główna klasa parsera. Oprócz wzmiankowanego wcześniej cache'u, zaimplementowałem nowe instrukcje oraz skończyłem prace nad snippetami tak, że w zasadzie już całe dziedziczenie szablonów działa, jak należy. Mam nadzieję, że pod koniec miesiąca biblioteka będzie już w takim stanie, że będzie nadawać się do ostrożnego użycia. Rzeczywiste projekty będą potrzebne, aby wykryć błędy oraz końcowe niedociągnięcia.&lt;/p&gt;    &lt;p&gt;W snippetach pojawiła się możliwość wstawienia zawartości rodzica za pomocą znacznika &lt;code&gt;opt:parent&lt;/code&gt;:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;yes&amp;quot; ?&amp;gt;
&amp;lt;opt:extend file=&amp;quot;test_inherited_a.tpl&amp;quot;&amp;gt;
	&amp;lt;opt:snippet name=&amp;quot;header&amp;quot;&amp;gt;
		&amp;lt;h1&amp;gt;Webmaster Of Puppets&amp;lt;/h1&amp;gt;
		&amp;lt;p&amp;gt;Here is the parent content:&amp;lt;/p&amp;gt;
		&amp;lt;opt:parent/&amp;gt;
		&amp;lt;p&amp;gt;End of the parent content&amp;lt;/p&amp;gt;
	&amp;lt;/opt:snippet&amp;gt;
&amp;lt;/opt:extend&amp;gt;
&lt;/pre&gt;


&lt;p&gt;W tym wypadku, jeżeli w pliku &lt;em&gt;test_inherited_a.tpl&lt;/em&gt; zdefiniowaliśmy snippet o identycznej nazwie, jego zawartość trafi na miejsce znacznika &lt;code&gt;opt:parent&lt;/code&gt;. Takie zagnieżdżanie działa wielopoziomowo. Gdyby i w tamtym snippecie użyto tego mechanizmu, OPT sięgnąłby jeszcze głębiej i tak dalej. Możliwe jest nawet wyciągnięcie domyślnej zawartości bloku &lt;code&gt;opt:insert&lt;/code&gt;, do którego ostatecznie snippet będzie wstawiony. Do całości dodałem na dokładkę prosty kod wykrywający nieskończoną rekurencję. Gdy taka zostanie wykryta, programista otrzyma elegancki, czerwony komunikat błędu :).&lt;/p&gt;


&lt;p&gt;Przy korzystaniu z nowego OPT powinna znacząco przydać się nowa konsola debugowa, rozszerzona w stosunku do analogicznej opcji w OPT 1.1.x. Główna zmiana dotyczy rozbicia listy wykonanych szablonów na mniejsze listy, które pokazują różne informacje:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lista wykonanych szablonów&lt;/li&gt;
&lt;li&gt;Lista aktualnie przekompilowanych szablonów&lt;/li&gt;
&lt;li&gt;Lista szablonów wczytanych z cache'u.&lt;/li&gt;
&lt;li&gt;Lista dziedziczenia szablonów - pokazuje użyte łańcuch zależności wraz z informacją, czy były one właśnie rekompilowane, czy nie.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dodatkowo, konsola wyświetla wszystkie ostrzeżenia, które w tej wersji nie są już bezczelnie ładowane na ekran. Można się do nich dostać jedynie poprzez konsolę debugową lub komunikat błędu, o ile ustawiliśmy odpowiedni poziom debugowania.&lt;/p&gt;


&lt;p&gt;Sprawa wydajności przedstawia się bardzo dobrze. Ostatecznie zamknąłem plik &lt;em&gt;opt.class.php&lt;/em&gt; w około 25 KB, w porównaniu do 32 KB z poprzedniej wersji, a na chwilę obecną wpływ jego rozmiaru jest dość dobrze widoczny w wynikach, jako że PHP musi załadować taki parser i go wstępnie skompilować do wewnętrznego bajtkodu. Naturalnie, gdy pozałączamy dużo szablonów, nie będzie to aż takie widoczne, ale mimo wszystko cieszę się z uzyskanego efektu.&lt;/p&gt;


&lt;p&gt;Paczkę można ściągnąć &lt;a href=&quot;http://www.invenzzia.org/download/opt-2.0.0-dev4.tar.gz&quot; hreflang=&quot;pl&quot;&gt;stąd&lt;/a&gt;. Zawiera ona również częściowo ukończoną polską dokumentację.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/OPT-200-dev4#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/OPT-200-dev4#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/17</wfw:commentRss>
      </item>
    
  <item>
    <title>Invenzzia.org... od nowa</title>
    <link>http://blog.invenzzia.org/pl/post/Invenzziaorg-od-nowa</link>
    <guid isPermaLink="false">urn:md5:589786ccda15b3f212a4aa4dffc074c2</guid>
    <pubDate>wto, 26 lut 2008 16:05:00 +0100</pubDate>
    <dc:creator>eXtreme</dc:creator>
        <category>Invenzzia</category>
        <category>invenzzia</category><category>website</category>    
    <description>&lt;p&gt;Powoli zaczynamy stawać na nogi. Miesiąc temu czas naglił i Zyx przygotował na szybko stronę naszej grupy oraz zainstalował devbloga. Dzisiaj prezentuję rozwiązanie bardziej rozbudowane. Niech będzie ono takim fundamentem i podstawą, dalszym krokiem w rozwoju naszej grupy. Strona została uzupełniona o teksty i informacje o grupie i choć wiele pracy jeszcze przed nami to z devblogiem sprawa jest już praktycznie zamknięta.&lt;/p&gt;    &lt;p&gt;Całego dotCleara zainstalowałem i skonfigurowałem od nowa. Nie ma już problemów z mieszaniem się języków wpisów, ponieważ blogi polski i angielski są teraz osobnymi miniblogami jednej instalacji. Detekcja języka usera zintegrowana jest z systemem zastosowanym na stronie i oparta jest na ciasteczkach i języku ustawionym w przeglądarce. Stworzyłem też bardziej czytelny i przyjazny szablon.&lt;/p&gt;


&lt;p&gt;A dlaczego nie Wordpress? Mam jakiś osobisty uraz, poza tym instytucja szablonów to tam praktycznie nie istnieje. Miałem swego czasu (nie)przyjemność tworzyć od podstaw jeden szablon i to była droga przez mękę. A z dotClearem2 już pracowałem wcześniej i bardzo przyjemnie się tu wszystko konfiguruje. Poza tym jest całkiem ciekawie napisany obiektowo na PHP5 więc za to duży plus. ;-)&lt;/p&gt;


&lt;p&gt;Grupa Invenzzia nie posiada jeszcze oficialnego logo, to widoczne na stronie głównej jest rozwiązaniem tymczasowym.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Invenzziaorg-od-nowa#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Invenzziaorg-od-nowa#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/15</wfw:commentRss>
      </item>
    
  <item>
    <title>Główna klasa OPT na ukończeniu</title>
    <link>http://blog.invenzzia.org/pl/post/Glowna-klasa-OPT-na-ukonczeniu</link>
    <guid isPermaLink="false">urn:md5:0e31e4a93c4e8d87810340a39dfbbd7a</guid>
    <pubDate>śro, 20 lut 2008 22:12:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>OPT2</category>    
    <description>&lt;p&gt;Owocem dzisiejszych zmagań z kodem źródłowym nowego OPT jest ukończenie pliku &lt;em&gt;opt.class.php&lt;/em&gt;, w którym (jak niektórym wiadomo) mieści się główna klasa parsera. Przyznam, że paradoksalnie plik ten był bardziej wymagający, niż kompilator. W tym drugim przypadku można sobie pozwolić na bardzo dużo, wystarczy pomysł na algorytm i przewidzenie, jak wpłynie on na resztę układu. Z główną klasą sprawa ma się troszeczkę inaczej. Jest ona dołączana za każdym razem, tak więc musi zawierać wszystko, co jest uruchamiane permanentnie. Musi to robić szybko, sprawnie i być nieduża. A tymczasem wymagania co do funkcjonalności rosną.&lt;/p&gt;    &lt;p&gt;Nowa wersja developerska będzie niekompatybilna z poprzednimi pod kątem interfejsu programistycznego. Aby zaimplementować cache tak, jak chciałem, musiałem przebudować niemal całą obsługę systemu wyjścia. W serii 1.x.x pojęcie systemu wyjścia w zasadzie nie istniało. To, czy wynik działania szablonu trafi na ekran, czy do zmiennej, zależało od wyboru odpowiedniej metody. Jakieś skomplikowane przełączenia i sztuczki kierowały wszystko do miejsca docelowego, aczkolwiek nie było w tym konsekwencji i strategia działania była średnio dopracowana. Cóż, tak wychodzi, jak się zaczyna od zachowywania podobieństw do Smarty'ego, a trzeba przypomnieć, że w początkowych, pionierskich czasach, było to jednym z założeń projektu. W OPTv2 istnieje jawnie zdefiniowany interfejs &lt;em&gt;ioptOutput&lt;/em&gt; pozwalający samodzielnie zaprogramować, co trzeba zrobić z wynikiem działania. Właśnie za jego pomocą realizowany będzie system cache, a jak - już tłumaczę.&lt;/p&gt;


&lt;p&gt;Dotąd w kodzie były dwa systemy wyjścia: &lt;em&gt;optNetOutput&lt;/em&gt; wysyłające wszystko na ekran i pilnujące przed dwukrotnym wysłaniem szablonu w trybie XML, oraz &lt;em&gt;optReturnOutput&lt;/em&gt; zwracające przechwycony rezultat. Dodałem do obu możliwość dekorowania ich czym innym i utworzyłem &lt;em&gt;optCachedOutput&lt;/em&gt; koncentrujące się w całości na obsłudze cache. Możliwości pozostaną po staremu, natomiast zmieni się sposób wywoływania i niestety trochę się rozbuduje inicjacja:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$cache = new optCachedOutput('./cache/'); // to jest cache, tu go konfigurujemy.
$tpl -&amp;gt; register(OPT_OUTPUT, 'my_cache', $cache);
$tpl -&amp;gt; decorate(OPT_OUT_SCREEN, 'my_cache');
$tpl -&amp;gt; decorate(OPT_OUT_RETURN, 'my_cache');

if(!$cache -&amp;gt; isCached('szablon.tpl', 'jakis_id'))
{
  // generuj dane
}

$cache -&amp;gt; setCache(5, 'jakis_id'); // włącz cache na 5 sekund
$tpl -&amp;gt; parse('szablon.tpl', 'my_cache');
&lt;/pre&gt;


&lt;p&gt;Spróbuję jakoś skrócić i uprościć to, co widać na początku, zwłaszcza że mi też się to specjalnie nie podoba. Ponadto muszę sprawdzić, czy dekoracji przypadkiem w niewłaściwą stronę (niezgodnie z logiką i intuicją) pod względem nazewnictwa nie zrobiłem :).&lt;/p&gt;


&lt;p&gt;Obsługa wtyczek nie jest jeszcze w pełni gotowa - ukończyłem jedynie część znajdującą się w &lt;em&gt;opt.class.php&lt;/em&gt;, jako że reszta może spokojnie być z pożytkiem dla wydajności wyekspediowana gdzie indziej. Podobnie, jak w OPT 1.1.3, będzie możliwość ustawienia kilku katalogów z pluginami, lecz parser nie będzie już żądać w nich praw do zapisu. Wrzucane tam były dodatkowe pliki opisujące zawartość katalogu i pozwalające załączyć jego zawartość bez konieczności jego skanowania. Jednak wiadomo, że im więcej include'ów, tym wolniej wszystko działa, a niektórzy potrafią tych wtyczek naprodukować tyle, że mają tam więcej plików, niż liczy sobie cały mój framework :D. Dlatego teraz OPT będzie ze wszystkich pluginów składać jeden mega-plik zawierający wszystko, czego potrzeba nam do szczęścia. Przy okazji będę mieć również nowy algorytm do następcy OPT Toolsetu, który teraz będzie obsługiwać już wszystkie biblioteki Open Power.&lt;/p&gt;


&lt;p&gt;Ostatnia sprawa dotyczy zestawu funkcji dostępnych w szablonach. Stormfly niedawno pisał na swoim blogu, że w OPT 1.1.x był on bezsensownie dobrany i w sumie miał rację. Popatrzyłem, co tam programiście daje Smarty i okazało się, że ma tam on w zanadrzu kilka ciekawych funkcji, które mogą być naprawdę przydatne. Wstępna lista zawiera zatem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;spacify&lt;/em&gt; - pomiędzy każde dwa sąsiednie znaki podanego ciągu wstawiany jest inny ciąg.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;indent&lt;/em&gt; - robi wcięcia w tekście.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;truncate&lt;/em&gt; - obcina tekst do maksymalnie podanej długości (można dodać nierozcinanie słów na pół)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;strip&lt;/em&gt; - redukuje wszystkie grupy białych znaków do pojedynczego znaku.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;capitalize&lt;/em&gt; - odpowiednik ucfirst()&lt;/li&gt;
&lt;li&gt;&lt;em&gt;upper&lt;/em&gt; - odpowiednik strtoupper()&lt;/li&gt;
&lt;li&gt;&lt;em&gt;lower&lt;/em&gt; - odpowiednik strtolower()&lt;/li&gt;
&lt;li&gt;&lt;em&gt;countWords&lt;/em&gt; - odpowiednik str_word_count()&lt;/li&gt;
&lt;li&gt;&lt;em&gt;countChars&lt;/em&gt; - odpowiednik strlen()&lt;/li&gt;
&lt;li&gt;&lt;em&gt;money&lt;/em&gt; - odpowiednik money_format(), lecz ustawienia można zapisać w konfiguracji OPT.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;number&lt;/em&gt; - odpowiednik number_format(), lecz ustawienia można zapisać w konfiguracji OPT.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;wordWrap&lt;/em&gt; - odpowiednik word_wrap()&lt;/li&gt;
&lt;li&gt;&lt;em&gt;replace&lt;/em&gt; - odpowiednik str_replace()&lt;/li&gt;
&lt;li&gt;&lt;em&gt;regexReplace&lt;/em&gt; - odpowiednik preg_replace(), lecz z ostatnim argumentem wysuniętym na początek, aby nie było niekonsekwencji.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;date&lt;/em&gt; - odpowiednik date() :)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;firstof&lt;/em&gt; - zwraca pierwszy niepusty element z podanych.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;nl2br&lt;/em&gt; - odpowiednik nl2br() :)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;array&lt;/em&gt; - tworzenie tablic po stronie szablonów.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;build&lt;/em&gt; - to, co w poprzednim OPT się nazywało apply(), ale jeszcze nie wiem, czy ostatecznie zostanie właśnie taka nazwa.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;W zestawie tym nie ma żadnych funkcji do escape'owania, ponieważ kompilator w wielu miejscach sam o to dba, a jeśli nie, będzie możliwość ręcznego zaznaczenia tego, aczkolwiek nie poprzez funkcję. W każdym razie chodzi o to, by kompilator wiedział, że coś jest escape'owane i z rozpędu sam czegoś od siebie nie dołożył, gdyż to równałoby się kaszanie na ekranie.&lt;/p&gt;


&lt;p&gt;Naprodukowałem całkiem sporo funkcjonalności, lecz koniec końców nie zdążyłem wszystkiego przetestować, tak więc nie mam pewności, czy cały ten kod w ogóle działa, jak należy, aczkolwiek jakichś specjalnych rewelacji się nie spodziewam. W końcu np. algorytmy cache'ujące zasadą działania nie różnią się specjalnie od tego, co było w poprzednich wersjach. Kolejny dev ukaże się już za parę dni.&lt;/p&gt;


&lt;p&gt;Na koniec mała statystyka:&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;- &lt;em&gt;opt.class.php&lt;/em&gt; - 24 KB i więcej już nie urośnie. W poprzedniej wersji plik ten był o całe 8 KB cięższy, a w sumie oferował mniej.&lt;br /&gt;
- &lt;em&gt;opt.compiler.php&lt;/em&gt; - 65 KB i wciąż rośnie.&lt;br /&gt;
- &lt;em&gt;opt.instructions.php&lt;/em&gt; - 25 KB i wciąż rośnie.&lt;/p&gt;&lt;/blockquote&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Glowna-klasa-OPT-na-ukonczeniu#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Glowna-klasa-OPT-na-ukonczeniu#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/13</wfw:commentRss>
      </item>
    
  <item>
    <title>OPT 2.0.0-dev3</title>
    <link>http://blog.invenzzia.org/pl/post/OPT-200-dev3</link>
    <guid isPermaLink="false">urn:md5:40f330500ef782c5627da5ebdf0d61ca</guid>
    <pubDate>pią, 15 lut 2008 13:26:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>OPT2</category>    
    <description>&lt;p&gt;Zgodnie z zapowiedzią częstszego publikowania postępów prac, udostępniamy dziś trzecią wersję developerską nowego Open Power Template'a, nad którą pracowałem przez ostatni tydzień. Tym razem poświęciłem sporo uwagi przetwarzaniu atrybutów OPT, które robią różne ciekawe rzeczy ze znacznikami, do których zostały dodane. Wstępna implementacja już była - nawet przykłady dotyczące &quot;opt:section&quot; znajdowały się już w paczce. Jednak aby w pełni spełniała oczekiwania, trzeba było rozbudować cały kod.&lt;/p&gt;    &lt;p&gt;Zamieszczam parę przykładów pokazujących, co ciekawego można już zrobić. Zacznijmy od czegoś prostego. W OPT do osadzania wyrażeń w treści służą nawiasy klamrowe, w których umieszczamy wyrażenie, np.&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;tekst tekst tekst {$blok} tekst tekst tekst
&lt;/pre&gt;


&lt;p&gt;Istnieje także instrukcja opt:put, która na pierwszy rzut oka wykonuje dokładnie to samo:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;tekst tekst tekst &amp;lt;opt:put value=&amp;quot;$blok&amp;quot;/&amp;gt; tekst tekst tekst
&lt;/pre&gt;


&lt;p&gt;Jednak dzięki temu, że to jest instrukcja, a nie nawiasy klamrowe, można z nią zrobić parę fajnych rzeczy przy pomocy atrybutów. Przypuśćmy, że chcemy uzyskać coś w stylu &quot;Wartość 1 / Wartość 2 / Wartość 3&quot;. Wystarczy nam do tego instrukcja opt:put, sekcja i separator:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;&amp;lt;p&amp;gt;&amp;lt;opt:put value=&amp;quot;$sekcja.wartosc&amp;quot; opt:section=&amp;quot;sekcja&amp;quot; str:separator=&amp;quot; / &amp;quot;/&amp;gt;&amp;lt;/p&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Jak widać, taka sekcja obejmuje także znacznik, do którego została doklejona i możemy umieszczać wartości elementów w pozostałych atrybutach. Separator domyślnie akceptuje wyrażenia, lecz gdy nie mamy ochoty na pisanie &lt;em&gt;separator=&quot;'cośtam'&quot;&lt;/em&gt; (cudzysłów, a później apostrof), zmieniamy po prostu przestrzeń nazw na &quot;str&quot;.&lt;/p&gt;


&lt;p&gt;Ukończyłem również implementację odwróconych apostrof, które w stosunku do poprzedniej wersji zmieniają swoje działanie. Tym razem programista może samodzielnie zaprogramować ich obsługę, pisząc zwykłą funkcję i przekazując jej nazwę do parsera. Można to wykorzystać np. do eleganckiej implementacji systemu językowego a'la gettext:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;&amp;lt;p&amp;gt;{`Parę przydatnych informacji...`}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;{`Autor:`} {$autor}&amp;lt;/p&amp;gt;
&lt;/pre&gt;


&lt;p&gt;W końcu ostatnia ze zmian. Skoro mamy parser XML, potrzebujemy paru instrukcji, które umożliwią twórcy szablonów bezpośrednie manipulowanie drzewem, np. dodanie atrybutu o zmiennej nazwie. OPT będzie zawierać dwie instrukcje do tego celu: &lt;em&gt;opt:tag&lt;/em&gt; oraz &lt;em&gt;opt:attribute&lt;/em&gt;. Ta druga została dodana do najnowszej wersji developerskiej. Możemy jej użyć, aby móc wczytać nazwę atrybutu z bloku:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;&amp;lt;div&amp;gt;
  &amp;lt;opt:attribute name=&amp;quot;$nazwa&amp;quot; value=&amp;quot;$wartosc&amp;quot;/&amp;gt;
  Treść...
&amp;lt;/div&amp;gt;
&lt;/pre&gt;


&lt;p&gt;To nie koniec - w połączeniu z sekcją uzyskujemy szybkie narzędzie do masowego dodawania atrybutów:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;&amp;lt;div&amp;gt;
  &amp;lt;opt:attribute name=&amp;quot;$atrybut.nazwa&amp;quot; value=&amp;quot;$atrybut.wartosc&amp;quot; opt:section=&amp;quot;atrybut&amp;quot;/&amp;gt;
  treść...
&amp;lt;/div&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Jeśli do takiej sekcji wyślemy tablicę: &lt;code&gt;array(0 =&amp;gt; array('nazwa' =&amp;gt; 'class', 'wartosc' =&amp;gt; 'dude'), array('nazwa' =&amp;gt; 'id', 'wartosc' =&amp;gt; 'lol'))&lt;/code&gt;, uzyskamy:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;&amp;lt;div class=&amp;quot;dude&amp;quot; id=&amp;quot;lol&amp;quot;&amp;gt;
  treść...
&amp;lt;/div&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Dość dużo czasu poświęciłem na rozwój dokumentacji. Wprawdzie dalej jest ona nieco z tyłu za kodem, ale powoli zaczyna go doganiać. Na ukończeniu jest opis sekcji, pojawiły się omówienia metod chronionych w &lt;em&gt;optClass&lt;/em&gt;, a nawet zalążki opisu kompilatora. Muszę też porządkować już istniejący kod, aby pasował do aktualnego stanu kodu oraz moich zamierzeń. Zachęcam do testowania i nadsyłania swych uwag.&lt;/p&gt;


&lt;p&gt;Download: &lt;a href=&quot;http://blog.invenzzia.org/pl/post/&quot; hreflang=&quot;pl&quot;&gt;http://www.invenzzia.org/download/opt-2.0.0-dev3.tar.gz&lt;/a&gt;&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/OPT-200-dev3#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/OPT-200-dev3#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/12</wfw:commentRss>
      </item>
    
  <item>
    <title>Nowy dev</title>
    <link>http://blog.invenzzia.org/pl/post/Nowy-dev</link>
    <guid isPermaLink="false">urn:md5:c99861121699affab67843d24771ede7</guid>
    <pubDate>sob, 09 lut 2008 10:52:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>OPT2</category>    
    <description>&lt;p&gt;Dodałem do strony dział &quot;Download&quot;, przy okazji umieszczając w nim nową wersję rozwojową Open Power Template'a. Znalazł się tam również nieduży skrypcik &quot;docgen&quot;, którego używamy do uruchamiania automatycznego parsowania dokumentacji w DocBooku. Nowe wersje rozwojowe będą teraz już publikowane znacznie częściej; w okresie dużego nasilenia prac być może nawet co dwa, trzy dni. Powód, dla którego nie były one dotąd tak częste, był brak automatyzacji, a przygotowanie takiej paczki pochłania trochę czasu (dla przykładu, umieszczenie nowej wersji OPT w Internecie zajmuje kilka godzin).&lt;/p&gt;    &lt;p&gt;W kolejnym devie znajduje się wszystko, co zaimplementowałem w przeciągu ostatniego miesiąca:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Niemal ukończone sekcje.&lt;/li&gt;
&lt;li&gt;Separatory.&lt;/li&gt;
&lt;li&gt;Pętle &quot;for&quot; i &quot;foreach&quot;.&lt;/li&gt;
&lt;li&gt;W większości ukończone dziedziczenie szablonów.&lt;/li&gt;
&lt;li&gt;Zarządzanie nagłówkami HTTP.&lt;/li&gt;
&lt;li&gt;Częściowo ukończone parsowanie prologu.&lt;/li&gt;
&lt;li&gt;Trochę poprawek w kompilatorze.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;W katalogu &quot;dev&quot; można znaleźć skrypty, za pomocą których testuję poprawność działania poszczególnych instrukcji. Są też unitTesty: gotowy zestaw do testów parsera wyrażeń oraz częściowo ukończony test API. Próbuję także opracować automatyczny tester poprawności działania samych instrukcji, żeby nie bawić się w ręczne wywoływanie. Problemy stwarzają nowe linie i białe znaki w kodzie wynikowym, które wprowadzają straszny zamęt w przypadku porównywania rezultatu z wzorcówką, przez co przygotowanie jednego głupiego testu zabiera dużo czasu. Jednak coś się wymyśli. Do działania wymagana jest instalacja pakietu phpUnit 3 z repozytorium PEAR.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Nowy-dev#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Nowy-dev#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/9</wfw:commentRss>
      </item>
    
  <item>
    <title>Licencjonowanie</title>
    <link>http://blog.invenzzia.org/pl/post/Licencjonowanie</link>
    <guid isPermaLink="false">urn:md5:0cfe4e92acf397cc05aa8ad990ae526e</guid>
    <pubDate>czw, 07 lut 2008 09:29:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Invenzzia</category>
        <category>licencjonowanie</category>    
    <description>&lt;p&gt;Co jakiś czas powraca jak bumerang sprawa licencji, na jakiej biblioteki są publikowane. Nie ulega wątpliwości, że jej dobór ma dość duże znaczenie dla popularyzacji projektu. Liberalne licencje są łatwe do interpretacji przez każdego oraz przez to bardzo łatwe w użyciu, lecz stwarzają prawo do pewnych nadużyć. Z drugiej strony mamy licencję GNU LGPL, na której dotąd był rozpowszechniany OPT. Zapewnia ona należytą ochronę kodowi, ale utrudnia łączenie z zamkniętym oprogramowaniem. A przecież biblioteka napisana w PHP dedykowana jest także twórcom stron WWW na zamówienie czy autorom kompletnych skryptów udostępnianych jako open-source bądź nie.&lt;/p&gt;    &lt;p&gt;Postanowiłem sprawdzić, ile zajęłoby przystępne wyjaśnienie warunków LGPL przeciętnemu użytkownikowi, szczególnie nastawionemu na działalność komercyjną. Dodałem do roboczej wersji dokumentacji odpowiedni dodatek i zacząłem pisanie. Wynikiem była rozciągająca się na dwa ekrany lista z objaśnieniami, dlaczego i jak twórcy serwisów WWW na zamówienie mogą z niej korzystać, kiedy trzeba udostępnić kod źródłowy i tak dalej. Oczywiście jest to nie do zaakceptowania - sam nie lubię zbytnio zbyt skomplikowanych ograniczeń i nie mam zamiaru zmuszać w ten sposób bez wyraźnego powodu innych.&lt;/p&gt;


&lt;p&gt;Powodem, dla którego wybrałem licencję GPL, była paradoksalnie chęć ochrony bibliotek przed zamianą w oprogramowanie własnościowe. Taki los spotkał kiedyś projekt Wine, rozpowszechniany początkowo na licencji MIT. Po pewnym czasie powstały zamknięte, komercyjne wersje dostępne bez kodu źródłowego. Co prawda jedna 150-kilobajtowa biblioteka specjalnej wartości handlowej nie ma, ale wolę spać spokojnie, tym bardziej, że mają pojawić się inne. Niestety nie ma żadnej licencji, która od razu pasowałaby do potrzeb:&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;- Dawała pełne prawa do łączenia zarówno z kodem open-source, jak i własnościowym pod warunkiem zachowania informacji o autorach, a w przypadku kodu źródłowego zachowania w stosunku do niego warunków licencji.&lt;br /&gt;
- Nakazywałaby rozpowszechnianie samej biblioteki (przeznaczonej do łączenia z innymi programami) także w postaci kodu źródłowego, co automatycznie implikowałoby zachowanie licencji.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Myślę, że takie ujęcie oprogramowania open-source najlepiej chroni prawa końcowego użytkownika. Zabraniając samodzielnej redystrybucji jedynie w postaci binarnej i ze zmienioną licencją, ma on pewność, że jeśli znajdzie jakąś paczkę OPT, będzie mógł z niej skorzystać na takich samych warunkach, jak z oryginału. Jeśli zaś trafi na zamkniętą wersję, oznacza to, że może być ona przystosowana, a na pewno jest przeznaczona do pracy z jednym, konkretnym skryptem.&lt;/p&gt;


&lt;p&gt;Najpewniejszym kandydatem na licencję jest jakaś zmodyfikowana wersja licencji BSD bez klauzuli ogłoszeniowej. Niestety trzeba się pobawić w dodanie do niej rzeczonego warunku w języku angielskim. Dobór właściwego słownictwa trochę potrwa i zapewne nie obejdzie się bez jakiejś pomocy bądź porady kogoś z zachodu. Dlatego wersje rozwojowe w dalszym ciągu będą dostępne na GNU LGPLv3, natomiast wersję finalną przygotuję już na nowej, znacznie łatwiejszej w użyciu licencji.&lt;/p&gt;


&lt;p&gt;Oprócz tego, chciałbym udostępnić także wersje płatne bibliotek, niezależnie od tego, że sam kod rozpowszechniany będzie niezwykle liberalnie. Nie byłyby one drogie - myślę, że cena wahałaby się w granicach 20-40 złotych tak, żeby mógł sobie na nią pozwolić niemal każdy zainteresowany. Dochód byłby przeznaczony głównie na utrzymanie domen, serwerów i cele promocyjne, gdyż utrzymanie tego wszystkiego trochę pieniędzy kosztuje. O ile pod względem kodu wersja taka nie różniłaby się od darmowej, nabywca dostawałby kilka bonusów. Aktualnie mam pomysły na następujące:&lt;/p&gt;


&lt;blockquote&gt;&lt;p&gt;- Dodatkowe materiały informacyjne.&lt;br /&gt;
- Prawo do włączenia materiałów informacyjnych do dokumentacji końcowej użytkownika.&lt;br /&gt;
- Przykładowe projekty wraz z kodem źródłowym i szeregiem komentarzy.&lt;br /&gt;
- Wcześniejszy dostęp do nowych wersji (np. tydzień)&lt;br /&gt;
- Dodatkowe wydania pojawiające się np. w przypadku znalezienia jakiegoś nie-krytycznego błędu, zawierające stosowną poprawkę.&lt;br /&gt;
- Możliwość umieszczenia szerszych informacji o projekcie wykorzystującym biblioteki na stronie grupy.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;Co o czymś takim sądzicie? Myślę, że na czymś takim zyskają wszyscy: my, bo nie będziemy musieli opłacać serwerów z własnej kieszeni; nabywcy, bo dostaną dodatkowe materiały i bonusy, a w dalszej konsekwencji wszyscy użytkownicy, jako że w celu ich przyciągnięcia powstawać będzie więcej tutoriali, artykułów itd.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Licencjonowanie#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Licencjonowanie#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/8</wfw:commentRss>
      </item>
    
  <item>
    <title>Dziedziczenie szablonów</title>
    <link>http://blog.invenzzia.org/pl/post/Dziedziczenie-szablonow</link>
    <guid isPermaLink="false">urn:md5:11eedc715a12fa05aa1c92aaf21f291d</guid>
    <pubDate>sob, 02 lut 2008 12:14:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>OPT2</category>    
    <description>&lt;p&gt;Przeważnie kod wynikowy strony komponuje się z kilku mniejszych szablonów zawierających fragmenty kodu. Istnieje wiele technik ich łączenia. W parserach dla PHP królują jak dotąd dwa rodzaje: ręczne uruchamianie szablonów we właściwej kolejności z poziomu kodu PHP oraz dyrektywa &lt;em&gt;include&lt;/em&gt;. Podobnie było także w poprzedniej wersji OPT, jednak w nowym wydaniu pierwszy ze sposób właściwie idzie do kasacji - o ile nie korzystamy z quirks mode, parser nie dopuści do tego, by wywołać metodę &lt;em&gt;parse()&lt;/em&gt; dwukrotnie. Początkowo miałem zamiar zrekompensować to, rozbudowując &lt;em&gt;include&lt;/em&gt; o tzw. sekwencje, lecz dnia pewnego na moim blogu Coldpeer zapytał się mnie, czy będzie dziedziczenie szablonów. Poszukałem, popatrzyłem i stwierdziłem, że to może być niezłe. Tak zaczęły się eksperymenty z implementacją.&lt;/p&gt;    &lt;p&gt;Dziedziczenie szablonów pojawiło się, z tego co wiem, w systemie szablonów pythonowego frameworka Django. Idea jest wzięta z programowania obiektowego, gdzie można dziedziczyć klasy, dodając do nich nowe metody, pola oraz nadpisując istniejące. Tutaj jest podobnie. Mamy szablon główny, w którym zaznaczamy pewne charakterystyczne miejsca i wypełniamy je standardową zawartością. Drugi szablon dziedziczy po głównym i może nadpisać wybrane miejsca własną treścią. Po nim może iść kolejny szablon i tak dalej.&lt;/p&gt;


&lt;p&gt;Okazało się, że spora część niezbędnej funkcjonalności była już w OPT 1.x - instrukcje &lt;em&gt;bind&lt;/em&gt; oraz &lt;em&gt;insert&lt;/em&gt; pozwalały przenosić całe fragmenty kodu w inne miejsce, także pomiędzy szablonami. Niestety, nie było tam odpowiedniego mechanizmu detekcji, czy zaszły jakieś modyfikacje w plikach i to trochę psuło całą koncepcję. Tak samo jego opracowanie dla nowej wersji było najtrudniejszym zadaniem, ponieważ nie wystarczy teraz jedynie sprawdzić, czy zaszły zmiany w szablonie, który wywołujemy, ale także czy coś nowego nie pojawiło się w szablonach bazowych! Z zamiarem definitywnego rozwiązania tego problemu siadłem do kodu wczoraj i parę godzin temu wszystko zadziałało tak, jak powinno:&lt;/p&gt;


&lt;p&gt;Szablon bazowy (&lt;em&gt;test_inherited_a.tpl&lt;/em&gt;):&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;html&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;yes&amp;quot; ?&amp;gt;
&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
	   &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;

&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; lang=&amp;quot;en_US&amp;quot; xml:lang=&amp;quot;en_US&amp;quot;&amp;gt;
 &amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Instruction test: snippet and insert&amp;lt;/title&amp;gt;
 &amp;lt;/head&amp;gt;
 &amp;lt;body&amp;gt;
  &amp;lt;opt:insert snippet=&amp;quot;header&amp;quot;&amp;gt;
   &amp;lt;h1&amp;gt;I'm a standard header&amp;lt;/h1&amp;gt;
   &amp;lt;p&amp;gt;Foo bar joe&amp;lt;/p&amp;gt;  
  &amp;lt;/opt:insert&amp;gt;
  
  &amp;lt;hr/&amp;gt;
  
  &amp;lt;opt:insert snippet=&amp;quot;content&amp;quot;&amp;gt;
  	&amp;lt;p&amp;gt;Well, i'm also a standard content.&amp;lt;/p&amp;gt;
  
  &amp;lt;/opt:insert&amp;gt;
  
  &amp;lt;hr/&amp;gt;
  
  &amp;lt;opt:insert snippet=&amp;quot;footer&amp;quot;&amp;gt;
  	&amp;lt;p&amp;gt;And I'm a footer.&amp;lt;/p&amp;gt;  
  &amp;lt;/opt:insert&amp;gt;
  
  &amp;lt;p&amp;gt;&amp;amp;copy; Pasteright 2008 by LMAO, It seems to work!&amp;lt;/p&amp;gt;
 &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Szablon dziedziczący po nim (&lt;em&gt;test_inherit_1.tpl&lt;/em&gt;):&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;yes&amp;quot; ?&amp;gt;
&amp;lt;opt:extend file=&amp;quot;test_inherited_a.tpl&amp;quot;&amp;gt;
	&amp;lt;opt:snippet name=&amp;quot;header&amp;quot;&amp;gt;
		&amp;lt;h1&amp;gt;Webmaster Of Puppets&amp;lt;/h1&amp;gt;
	&amp;lt;/opt:snippet&amp;gt;

	&amp;lt;opt:snippet name=&amp;quot;content&amp;quot;&amp;gt;
		&amp;lt;p&amp;gt;Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus ut tellus id nulla adipiscing eleifend. Sed dictum accumsan ante. Nullam at nisl vitae elit aliquet fringilla. Praesent egestas eros eget tellus. Praesent id odio a sapien rhoncus vehicula. Nunc fringilla, diam eget euismod tempor, tortor metus tincidunt sapien, eu cursus magna tellus at risus. Praesent non tellus eget magna facilisis pulvinar. Praesent libero mi, adipiscing a, pharetra eget, condimentum sodales, mi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Donec ac elit. Duis iaculis tortor a metus. Aliquam id purus et eros faucibus fringilla. Praesent quis quam. In lectus urna, fringilla sit amet, iaculis eget, aliquet ac, quam. Donec vulputate dui sit amet lectus. Aenean tempor, orci at pretium ornare, tortor tortor venenatis ligula, eget blandit nisi risus eget dolor. Duis nunc neque, sodales porta, viverra non, tristique eu, sem. Curabitur magna neque, blandit ullamcorper, congue quis, tristique ut, felis.&amp;lt;/p&amp;gt;
	&amp;lt;/opt:snippet&amp;gt;

	&amp;lt;opt:snippet name=&amp;quot;footer&amp;quot;&amp;gt;
		&amp;lt;p&amp;gt;Bye!!!&amp;lt;/p&amp;gt;
	&amp;lt;/opt:snippet&amp;gt;
&amp;lt;/opt:extend&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Do tego kod PHP:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;&amp;lt;?php

	define('OPT_DIR', '../lib/');
	require(OPT_DIR.'opt.class.php');

	try
	{
		$tpl = new optClass;
		$tpl -&amp;gt; sourceDir = './templates/';
		$tpl -&amp;gt; compileDir = './templates_c/';
		$tpl -&amp;gt; stripWhitespaces = false;
		$tpl -&amp;gt; printComments = false;
		$tpl -&amp;gt; setup();
		
		$tpl -&amp;gt; parse('test_inherit_1.tpl');
	}
	catch(optException $e)
	{
		optErrorHandler($e);
	}
?&amp;gt;
&lt;/pre&gt;


&lt;p&gt;A rezultat widać poniżej:&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://blog.invenzzia.org/public/images/template_inheritance.png&quot;&gt;&lt;img src=&quot;http://blog.invenzzia.org/public/images/.template_inheritance_m.jpg&quot; alt=&quot;Template inheritance&quot; style=&quot;display:block; margin:0 auto;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Parę faktów:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Jeżeli zmodyfikujemy dowolny z szablonów, po którym nasz szablon dziedziczy, OPT wykona rekompilację i zmiana zostanie natychmiast uwzględniona.&lt;/li&gt;
&lt;li&gt;Jeżeli usuniemy dowolną z instrukcji &quot;opt:snippet&quot;, wyświetli nam się domyślna zawartość zdefiniowana wewnątrz &quot;opt:insert&quot;.&lt;/li&gt;
&lt;li&gt;Istnieje możliwość nadpisania już zdefiniowanego snippeta przez leżący wyżej w hierarchii szablon. Będę implementował mechanizm odwołania się do zawartości rodzica (jakaś instrukcja &quot;opt:parent&quot;).&lt;/li&gt;
&lt;li&gt;Można to mieszać z &quot;opt:include&quot; oraz &quot;opt:sequence&quot; (mechanizm sekwencji).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ponadto bardzo możliwe, że dziedziczenie szablonów w ostatecznym rozrachunku może działać szybciej, niż tradycyjna metoda, aczkolwiek kosztem miejsca na dysku. Po prostu jak mamy dziedziczenie &quot;A po  B po C&quot;, wywołując szablon A, caluteńki kod wynikowy ze wszystkich szablonów jest zrzucany właśnie do A. Zmniejsza to ilość odwołań do dysku, gdyż uruchomienie jednego wielkiego szablonu jest mniej kosztowne, niż tej samej treści rozbitej na 3 mniejsze pliki. Z drugiej strony, w podstawowym trybie OPT wciąż sprawdza czasy modyfikacji (tyle że robi mniej testów). Póki co są to jedynie przypuszczenia. Dopiero po skończeniu i zrobieniu porządnego benchmarku będę w stanie podać konkretne liczby. Chociaż dodam, że z ciekawości puściłem sobie prosty test (lista 15 elementów):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;OPT 1.x: 1850 req/s&lt;/li&gt;
&lt;li&gt;OPT 2.0: 2100 req/s&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nie są to wyniki ostateczne - trzeba wziąć pod uwagę, że nowy plik &lt;em&gt;opt.class.php&lt;/em&gt; wciąż nie ma sporej części opcji, które trochę zwiększą jego objętość, a ponadto nie zaimplementowałem jeszcze niektórych optymalizacji. Tak więc można się spodziewać, że nowe możliwości nie odbiją się niekorzystnie na wydajności, a nawet jest szansa na coś odwrotnego - nowa wersja będzie szybsza.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Dziedziczenie-szablonow#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Dziedziczenie-szablonow#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/5</wfw:commentRss>
      </item>
    
  <item>
    <title>Głębsze przetwarzanie</title>
    <link>http://blog.invenzzia.org/pl/post/Glebsze-przetwarzanie</link>
    <guid isPermaLink="false">urn:md5:816c5be6adacf6b106cabd838e3353cd</guid>
    <pubDate>czw, 31 sty 2008 13:08:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>Open Power Forms</category>    
    <description>&lt;p&gt;Ostatni projekt, jaki realizowałem z użyciem Open Power Forms, ukazał kilka słabych punktów aktualnej implementacji. Było tam kilka formularzy umożliwiających masowe dodawanie rekordów jednego typu, tj. była sobie tabelka, w kolumnach pola: Imię, Nazwisko, PESEL, coś tam innego i było tak 30 wierszy. Razem można było za jednym zamachem dodać do 30 rekordów. O ile metodę &lt;em&gt;map()&lt;/em&gt; dało się jeszcze dość łatwo zmusić do przetworzenia czegoś takiego bez rozpisywania się, o tyle połączenie z szablonem zaczęło już wtedy szwankować.&lt;/p&gt;    &lt;p&gt;Kod prezentował się następująco:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$this -&amp;gt; map('names', new opfArrayContainer(
	new opfConstraint(MAP_TYPE, TYPE_STRING),
	new opfConstraint(MAP_LEN_GT, 2)
), OPF_OPTIONAL);
$this -&amp;gt; map('surnames', new opfArrayContainer(
	new opfConstraint(MAP_TYPE, TYPE_STRING),
	new opfConstraint(MAP_LEN_GT, 2)
), OPF_OPTIONAL);
$this -&amp;gt; map('pesels', new opfArrayContainer(
	new sConstraint(MAP_PESEL)
), OPF_OPTIONAL);
&lt;/pre&gt;


&lt;p&gt;Innymi słowy, do skryptu musiało przyjść np. pole &quot;names&quot; będące tablicą z 30-ma komórkami, w których były poszczególne imiona. Okazało się, że gdy w takiej strukturze zrobiło się gdzieś błąd powodujący, że nie chciało to przejść przez kontrolę poprawności, renderer formularzy wariował i w ogóle nie wiedział, który komponent ma oznaczyć jako błędny. Ostatecznie dodałem do kodu biblioteki na sztywno obsługę stałej &lt;em&gt;IGNORE_OPF_ERRORS&lt;/em&gt;, tak aby po prostu siedział wtedy cicho i wyświetlał formularz bez żadnego oznaczania na czerwono itd.&lt;/p&gt;


&lt;p&gt;Oczywiście takie rozwiązanie na dłuższą metę nie przejdzie i trzeba wymyślić jakieś usprawnienie. W dodatku dobrze, aby to usprawnienie elegancko komponowało się z resztą kodu i faktycznie było intuicyjne do pojęcia, bo nie sztuka dodać coś w 20 minut, a miesiąc później klnąć, że się nie chciało dokładniej pomyśleć. Najlepsze są rozwiązania proste i skuteczne, dlatego zacząłem się zastanawiać, czy można opisać formularz kilkoma definicjami i przekształceniami tak, aby na ich podstawie można było uzyskać dowolną konfigurację z gwarancją, że OPF ją obsłuży. Mój pomysł opiera się na tym, aby zejść nieco głębiej i zrównać w definicji formularz oraz pole formularza. Powodem jest kilka podobieństw:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Oba mogą mieć pewną wartość (przy czym dla formularza definiujemy ją jako zbiór wartości wszystkich pod-elementów)&lt;/li&gt;
&lt;li&gt;Oba mają pewien stan oraz mogą go zmieniać w trakcie przetwarzania.&lt;/li&gt;
&lt;li&gt;Oba są przetwarzane.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Teraz wystarczy, że potraktujemy formularz jako kontrolkę, która może przechowywać inne pola. Jeżeli spróbujemy teraz wymodelować powyższy przykład, wyglądałoby to mniej więcej tak: tworzymy sobie formularz dla pojedynczej osoby: Imię, Nazwisko, PESEL i coś tam jeszcze. Następnie osadzamy go w większym formularzu i zapętlamy tak, aby mógł pojawić się do 30-tu razy. Możemy także łatwo uzyskać efekt umieszczenia w &lt;em&gt;opfArrayContainer()&lt;/em&gt; pojedynczego pola tak, jak to było dotychczas - po prostu umieszczamy w takiej pętli nie cały formularz, ale pojedynczą kontrolkę.&lt;/p&gt;


&lt;p&gt;Pozostaje jeszcze kwestia nauczenia komponentów korzystania z takiej struktury, ale nie sądzę, aby było przesadnie skomplikowane, zwłaszcza w świetle tego, co szykuje nowy Open Power Template.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Glebsze-przetwarzanie#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Glebsze-przetwarzanie#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/4</wfw:commentRss>
      </item>
    
  <item>
    <title>Zaczynamy</title>
    <link>http://blog.invenzzia.org/pl/post/Zaczynamy</link>
    <guid isPermaLink="false">urn:md5:eee1b47b91b237e2993081c7e3fabb86</guid>
    <pubDate>śro, 30 sty 2008 12:29:00 +0100</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Invenzzia</category>
        <category>invenzzia</category><category>website</category>    
    <description>&lt;p&gt;Witam na devblogu nowej grupy programistycznej Invenzzia. Jest kilka powodów, dla których ją powołałem. Pierwszy i najważniejszy to chęć zapewnienia porządnej organizacji i infrastruktury projektom open-source, które już tworzę i które dopiero powstaną. Na początek przetransferowałem na jej poczet istniejący już od trzech lat system szablonów Open Power Template, który tutaj stanie się zalążkiem rodziny bibliotek Open Power Libraries. Aktualnie jesteśmy na początku etapu samoorganizowania się i nasza witryna internetowa będzie uruchamiana po kawałku w miarę jak powstaną kolejne jej elementy. Postaram się, aby nie potrwało to długo.&lt;/p&gt;    &lt;p&gt;Invenzzia ma zupełnie odmienny charakter, niż to, co miało miejsce przy Open Power Board. Niemal wszystkich znam osobiście, zaś ze wszystkimi utrzymuję stały kontakt, co oczywiście pozwala na aktywniejsze angażowanie się w prace. Poza nazwą jednego projektu i jego kodem nie odziedziczyliśmy po wcześniejszych reinkarnacjach absolutnie nic, tak więc sprawa własności poszczególnych elementów oraz odpowiedzialności za ich utrzymanie jest zupełnie jasna. Własny serwer pozwala też na uruchomienie paru usług, o których wcześniej mogliśmy tylko pomarzyć.&lt;/p&gt;


&lt;p&gt;Pora przedstawić członków grupy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;eXtreme - programista PHP/JavaScript, a także spec od XHTML/CSS. Prywatnie mój brat.&lt;/li&gt;
&lt;li&gt;Radzio - programista PHP/JavaScript. Prywatnie kumpel z roku.&lt;/li&gt;
&lt;li&gt;Slump - konsultant-menedżer-PR. Prywatnie jedyna osoba, która w OpenPB oprócz mnie faktycznie robiła coś pożytecznego.&lt;/li&gt;
&lt;li&gt;Zyx - czyli ja, odpowiedzialny za projekty bibliotek, silników itd.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Naszymi pierwszymi zadaniami będzie ukończenie Open Power Template 2 oraz Open Power Forms. Mamy też kilka dalszych pomysłów, których realizacja rozpocznie się nieco później. W każdym razie postaramy się dostarczyć świetny zestaw wysokiej jakości narzędzi open-source dla PHP prezentujący zupełnie nowe podejście do wielu zdawałoby się, oczywistych spraw.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Zaczynamy#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Zaczynamy#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/rss2/comments/1</wfw:commentRss>
      </item>
    
</channel>
</rss>