<?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/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Invenzzia... po polsku - Open Power Template</title>
  <link>http://blog.invenzzia.org/pl/</link>
  <atom:link href="http://blog.invenzzia.org/pl/feed/category/Open-Power-Template/rss2" rel="self" type="application/rss+xml"/>
  <description></description>
  <language>pl</language>
  <pubDate>sob, 15 sty 2011 22:56:54 +0100</pubDate>
  <copyright>Copyright &amp;copy; Invenzzia</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Open Power Template 2.0-RC1</title>
    <link>http://blog.invenzzia.org/pl/post/Open-Power-Template-2.0-RC1</link>
    <guid isPermaLink="false">urn:md5:fa6d32181a6fb66b0d38b1c8e7c4614c</guid>
    <pubDate>wto, 12 maj 2009 13:17:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>nowe wersje</category><category>OPT2</category>    
    <description>&lt;p&gt;W końcu, po prawie półtorarocznych pracach zbliżamy się do szczęśliwego finału. Od dzisiaj do ściągnięcia jest Open Power Template w wersji 2.0-RC1. Biblioteka wygląda już na kompletną i wystarczająco stabilną do większości zastosowań, wliczając w to środowiska rozwojowe i produkcyjne. Wciąż istnieje szansa, że zostanie odkryty jakiś poważny błąd, ale osobiście nie sądzę, by doszło aż do tego. OPT przez ostatnie 4,5 miesiąca poddawany był szeroko zakrojonym beta-testom i szlifowaniu, zarówno poprzez liczącą już prawie pół tysiąca elementów kolekcję testów, jak i dwie rzeczywiste aplikacje, które zostały przy jego pomocy napisane.&lt;/p&gt;    &lt;h2&gt;Skąd ściągnąć?&lt;/h2&gt;


&lt;p&gt;Oczywiście biblioteka jest dostępna do pobrania z naszej &lt;a href=&quot;http://www.invenzzia.org/en/download&quot; hreflang=&quot;en&quot;&gt;strony WWW&lt;/a&gt;. Oprócz standardowych paczek, po raz pierwszy publikujemy również oficjalne archiwa PHAR. PHAR to skrót od &lt;em&gt;PHP ARchive&lt;/em&gt;, czyli paczek z gotowym do uruchomienia kodem PHP podobnych w działaniu do plików JAR w Javie. Odpowiednie rozszerzenie do ich wykonywania będzie częścią PHP od wersji 5.3.0, a istnieje możliwość jego doinstalowania również do dotychczasowych wersji. Ponieważ okazało się, że nasz dział Download nie bardzo radzi sobie z taką ilością różnorodnych plików, póki co odnośniki zamieszczam tutaj:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://static.invenzzia.org/files/opt-phar-2.0-rc1.tar.bz2&quot; hreflang=&quot;en&quot;&gt;PHAR-y w formacie TAR.BZ2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://static.invenzzia.org/files/opt-phar-2.0-rc1.tar.gz&quot; hreflang=&quot;en&quot;&gt;PHAR-y w formacie TAR.GZ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://static.invenzzia.org/files/opt-phar-2.0-rc1.zip&quot; hreflang=&quot;en&quot;&gt;PHAR-y w formacie ZIP&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Każda paczka zawiera dwa pliki PHAR: dla OPL oraz dla OPT, teksty licencji użytkownika oraz dokument README. Nie ma w niej dokumentacji.&lt;/p&gt;


&lt;h2&gt;Co dalej?&lt;/h2&gt;


&lt;p&gt;&lt;em&gt;Release Candidate&lt;/em&gt; nie oznacza końca rozwoju projektu - została przecież jeszcze choćby wersja stabilna, a w dalszej perspektywie mnóstwo planów do wydania 2.1. Jednak teraz na jakiś czas rozwój OPT zostanie spowolniony, gdyż w kolejce czekają również inne projekty. Musimy w dalszym ciągu rozbudowywać bazę poradników i artykułów, gdyż bez tego właściwie nie ma szans na przyciągnięcie nowych użytkowników. Ponadto na swoją kolej czekają Open Power Classes, Open Power Forms oraz port dla Zend Frameworka.&lt;/p&gt;


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


&lt;p&gt;Na zakończenie pragniemy podziękować wszystkim dotychczasowym użytkownikom biblioteki za wytrwałość, szczególnie tym, którzy aktywnie włączyli się w proces rozwoju. Ta biblioteka powstaje właśnie dla was.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/Open-Power-Template-2.0-RC1#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/Open-Power-Template-2.0-RC1#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/atom/comments/59</wfw:commentRss>
      </item>
    
  <item>
    <title>OPT: Raport z prac</title>
    <link>http://blog.invenzzia.org/pl/post/OPT%3A-Raport-z-prac</link>
    <guid isPermaLink="false">urn:md5:3ad4101153a2a87a8638d3b2b2d51009</guid>
    <pubDate>pią, 19 wrz 2008 14:13:00 +0200</pubDate>
    <dc:creator>Zyx</dc:creator>
        <category>Open Power Template</category>
        <category>development</category><category>OPT2</category>    
    <description>&lt;p&gt;Przyszła pora na złożenie kolejnego raportu z prac nad OPT. W ostatnim czasie biblioteka wzbogaciła się o kilka nowych opcji, zamkniętych zostało również kilka błędów z bugtrackera. Z najważniejszych zmian można powitać (w końcu) tryb tekstowy figurujący w anglojęzycznej terminologii jako Quirks Mode. Pojawiła się nowa sekcyjna instrukcja: opt:selector, która zastępuje opt:paginator. Natomiast jeśli chodzi o funkcje, dodane zostało pełne wsparcie dla zmiany kolejności argumentów wykonywanej przez kompilator, co pozwala uniknąć tworzenia nakładek tylko po to, by ujednolicić wszystko.&lt;/p&gt;    &lt;p&gt;Istotna zmiana dotyczy zasobów oraz dyrektywy &lt;code&gt;sourceDir&lt;/code&gt;. Zrezygnowałem z pojęcia zasobu oraz interfejsu &lt;code&gt;Opt_Resource_Interface&lt;/code&gt; na rzecz strumieni PHP, które również można dowolnie oprogramowywać, a przy okazji oferują one znacznie większe możliwości przy wykorzystaniu standardowych funkcji. Ich konfigurowanie odbywa się teraz poprzez dyrektywę &lt;code&gt;sourceDir&lt;/code&gt;, która może teraz przyjmować jako wartość również tablicę asocjacyjną:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$tpl-&amp;gt;sourceDir = array(
   'file' =&amp;gt; '/sciezka/templates/',
   'db' =&amp;gt; 'database://moja_baza/'
);

// system plików
$tpl-&amp;gt;parse('szablon.tpl');

// baza danych
$tpl-&amp;gt;parse('db:szablon.tpl');
&lt;/pre&gt;


&lt;p&gt;Oczywiście we wspomnianym przykładzie trzeba ręcznie sobie strumień &quot;db&quot; utworzyć, a szczegóły znajdują się w dokumentacji PHP.&lt;/p&gt;


&lt;p&gt;Nowa instrukcja, &lt;code&gt;opt:selector&lt;/code&gt;, jest połączeniem sekcji oraz czegoś w rodzaju instrukcji &quot;switch&quot;. Umożliwia proste definiowanie różnych wariantów wyświetlenia elementu, a wybór odpowiedniego następuje na podstawie jednego z pól elementu, domyślnie o nazwie &quot;item&quot;. Od strony kodu, wygląda to bardzo podobnie do składni dawnej instrukcji &lt;code&gt;opt:paginator&lt;/code&gt;, którą nawiasem mówiąc można bardzo łatwo odtworzyć:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;opt:selector name=&amp;quot;strony&amp;quot;&amp;gt;
  &amp;lt;opt:page&amp;gt;[ &amp;lt;a parse:href=&amp;quot;$strony.adres&amp;quot;&amp;gt;{$strony.numer}&amp;lt;/a&amp;gt; ]&amp;lt;/opt:page&amp;gt;
  &amp;lt;opt:active&amp;gt;[ &amp;lt;a parse:href=&amp;quot;$strony.adres&amp;quot; class=&amp;quot;active&amp;quot;&amp;gt;{$strony.numer}&amp;lt;/a&amp;gt; ]&amp;lt;/opt:active&amp;gt;
  &amp;lt;opt:dots&amp;gt;...&amp;lt;/opt:dots&amp;gt;
&amp;lt;/opt:selector&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Całość współpracuje ze snippetami i posiada wszystkie inne właściwości sekcji, włącznie z &lt;code&gt;opt:selectorelse&lt;/code&gt;, a nawet atrybutem &lt;code&gt;opt:selector&lt;/code&gt; pozwalającym zmienić dowolny znacznik w tę instrukcję.&lt;/p&gt;


&lt;p&gt;System dziedziczenia szablonów został wzbogacony o nową możliwość, mianowicie dołączanie dodatkowego szablonu, tylko że w przeciwną stronę (coś na wzór szablonów kompilacyjnych z OPT 1.x):&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;xml&quot;&gt;&amp;lt;!-- szablon.tpl --&amp;gt;
&amp;lt;opt:root include=&amp;quot;inny_szablon.tpl&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;Tutaj mamy jakiś kod...&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;I możemy użyć snippetów z pliku inny_szablon.tpl&amp;lt;/p&amp;gt;
  &amp;lt;opt:insert snippet=&amp;quot;foo&amp;quot; /&amp;gt;
&amp;lt;/opt:root&amp;gt;

&amp;lt;!-- inny_szablon.tpl --&amp;gt;
&amp;lt;opt:root&amp;gt;
  &amp;lt;opt:snippet name=&amp;quot;foo&amp;quot;&amp;gt;
    Treść snippetu.
  &amp;lt;/opt:snippet&amp;gt;
&amp;lt;/opt:root&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Niestety, ta jedna rzecz musi być kompilowana rekurencyjnie, przynajmniej na razie, dlatego odradzam robienie jakichś super-długich łańcuchów w stylu &quot;A dołącza B, który dołącza C, który dołącza D, który dołącza E&quot; itd. Na pocieszenie dodam, że i tutaj został zamontowany wykrywacz nieskończonej rekurencji, który przerwie dołączanie, jeśli stwierdzi, że doprowadzi to do zapętlenia.&lt;/p&gt;


&lt;p&gt;Ostatnia zmiana, to tryb quirks. Nie wiem, czy oczekiwany przez wszystkich, ale na pewno potrzebny, by OPT mógł sięgać tam, gdzie żaden zwykły kompilator XML nie sięgnie - do przetwarzania dowolnych dokumentów tekstowych. W skrócie - kompilator wyłapuje wtedy wyłącznie znaczniki należące do OPT (instrukcje), cała reszta traktowana jest natomiast jak zwykły tekst, podobnie jak to miało miejsce w OPT 1.1.x. Włączyć go można globalnie albo lokalnie dla pojedynczego szablonu:&lt;/p&gt;

&lt;pre name=&quot;code&quot; class=&quot;php&quot;&gt;$tpl-&amp;gt;mode = Opt_Class::QUIRKS_MODE;
$tpl-&amp;gt;parse('szablon.tpl', Opt_Class::OUT_SCREEN, NULL, Opt_Class::QUIRKS_MODE);
&lt;/pre&gt;


&lt;p&gt;Najnowsza wersja kodu dostępna jest w SVN-ie, niedługo zaś pojawi się OPL 2.0.0-dev8.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.invenzzia.org/pl/post/OPT%3A-Raport-z-prac#comment-form</comments>
      <wfw:comment>http://blog.invenzzia.org/pl/post/OPT%3A-Raport-z-prac#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.invenzzia.org/pl/feed/atom/comments/35</wfw:commentRss>
      </item>
    
  <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/atom/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/atom/comments/33</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/atom/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/atom/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/atom/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/atom/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/atom/comments/20</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/atom/comments/17</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/atom/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/atom/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/atom/comments/9</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/atom/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/atom/comments/4</wfw:commentRss>
      </item>
    
</channel>
</rss>
