<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>MGdevelop &#187; MediaWiki</title>
	<atom:link href="http://mgdevelop.pl/index.php/kategoria/cmsy/mediawiki/feed/" rel="self" type="application/rss+xml" />
	<link>http://mgdevelop.pl</link>
	<description>Programming is an art form that fights back</description>
	<lastBuildDate>Thu, 07 Jul 2011 16:59:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Dodawanie tagów do MediaWiki</title>
		<link>http://mgdevelop.pl/index.php/2010/09/dodawanie-tagow-do-mediawiki/</link>
		<comments>http://mgdevelop.pl/index.php/2010/09/dodawanie-tagow-do-mediawiki/#comments</comments>
		<pubDate>Tue, 28 Sep 2010 14:48:47 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[MediaWiki]]></category>
		<category><![CDATA[parser]]></category>
		<category><![CDATA[rozszerzenie]]></category>
		<category><![CDATA[tag]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=507</guid>
		<description><![CDATA[Jeśli posiadamy własną encyklopedię na silniku MediaWiki to zapewne chcemy aby naszym redaktorom pisanie stron sprawiało jak najmniej problemów ale... <a href="http://mgdevelop.pl/index.php/2010/09/dodawanie-tagow-do-mediawiki/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Jeśli posiadamy własną encyklopedię na silniku MediaWiki to zapewne chcemy aby naszym redaktorom pisanie stron sprawiało jak najmniej problemów ale jednocześnie aby tworzona przez nas wiki wyglądała jak najładniej. Pchanie htmla w kod stron mija się z celem. Szablony? Sprawdzą się. Ale co jeśli chcemy dać więcej możliwości edytującym np. automatyczne generowanie obrazka? Składnia MW na to nie pozwala ale PHP już tak. Musimy wiec dodać własne tagi do składni wiki za pomocą rozszerzenia!</p>
<p><span id="more-507"></span></p>
<h1>Przygotowanie</h1>
<p>Na początek ustalmy jaki mamy cel w naszej pracy. W tym poradniku chciałbym pokazać jak dodać tag &lt;ramka&gt; który pozwoli na szybkie tworzenie rameczek z obrazkowym tłem i treścią w środku. Jako tło będzie można ustawić dowolną grafikę spośród zuploadowanych na serwer wpisując jej nazwę jako wartość atrybutu <em>grafika</em>.</p>
<p>Teraz czas na napisanie rozszerzenia. Zaczniemy od stworzenia pliku z rozszerzeniem php. Musimy ten plik umieścić w folderze extensions naszej instalacji MW. U mnie będzie to <em>extensions/nowetagi.php</em>. Tak przygotowany plik musimy podpiąć do skryptu. W tym celu otwieramy plik LocalSettings i mniej więcej po środku dopisujemy linijkę:</p>
<pre class="brush: php">require_once("extensions/nowetagi.php");</pre>
<h1>Włączanie parsowania</h1>
<p>Kolejnym krokiem w naszej pracy będzie otwarcie pliku <em>nowetagi.php</em> i dodanie odpowiedniego zdarzenia wewnątrz znaczników php:</p>
<pre class="brush: php">$wgHooks['ParserFirstCallInit'][] = 'mojParser';</pre>
<p>Powyższa linijka spowoduje, że w momencie jak MediaWiki będzie parsował artykuł to wywoła funkcję mojParser by dowiedzieć się jak parsować tagi obsługiwane przez nasze rozszerzenie. Poniżej tej linijki umieszczamy ciało wspomnianej funkcji:</p>
<pre class="brush: php">function mojParser( &amp;$parser ) {
   $parser-&gt;setHook( 'ramka', 'parsowanieRamka');
   return true;
}</pre>
<p>W podanym przykładzie poinformowaliśmy parser, że tag &lt;ramka&gt; ma być obsługiwany za pomocą funkcji <em>parsowanieRamka()</em>. W obrębie jednej funkcji mojParser możemy dodać nielimitowaną liczbę nowych tagów. Ważne jest tylko aby na końcu zwrócić <em>true</em>.</p>
<h1>Funkcja parsująca</h1>
<p>Teraz zdefiniujmy funkcję <em>parsowanieRamka().</em></p>
<pre class="brush: php">function parsowanieRamka( $input, $args, $parser, $frame ) {
}</pre>
<p>Póki co ciało funkcji jest puste. Musimy bowiem najpierw wyjaśnić co zawierają przekazane argumenty. Jak wiadomo tagi dzielą się na dwuelementowe (&lt;ramka&gt;&lt;/ramka&gt;) i jednoelementowe (&lt;cytat /&gt;). Jeśli parsowany tag składa się z otwarcia i zamknięcia to zmienna $input będzie zawierała to co znajduje się pomiędzy czyli inaczej mówiąc zawartość tagu. Zmienna $args jest zaś tablicą o indeksach identycznych jak atrybuty parsowanego tagu i z wartościami równymi wartościom tych atrybutów. Dla przykładu tag <em>&lt;ramka grafika=&#8221;tlo.jpg&#8221;&gt;Dowolny tekst&lt;/ramka&gt;</em> zostanie podzielony na zmienną <em>$input</em> o wartości <em>Dowolny tekst</em> oraz na jednoelementową tablicę <em>$args</em> gdzie $args['grafika']=&#8217;tlo.jpg&#8217;. Pozostałe argumenty przekazane funkcji <em>parsowanieRamka()</em> nie są dla nas istotne.</p>
<p>Uzbrojeni w powyższą wiedzę możemy zacząć pisać skrypt który zwróci kod html w miejsce tagu w artykule. Musimy jeszcze tylko pobrać adres URL do grafiki której nazwa została przekazana w atrybucie <em>grafika</em>.</p>
<pre class="brush: php">if(!empty($args['grafika'])){
   $file = wfFindFile($args['grafika']);
   $url = $file-&gt;getFullUrl();
}</pre>
<p>Powyższa instrukcja sprawi, że jeśli zdefiniowano wartość atrybutu grafika to zmienna $url będzie przechowywała bezwzględny adres do tego pliku. Możemy ją teraz użyć przy generowaniu pierwszej części kodu wynikowegoi ustawić obrazek jako tło bloku:</p>
<pre class="brush: php">$output = '&lt;div class="ramka" style="background-image: url('.$url.');"&gt;';</pre>
<p>Teraz trzeba dołączyć do tego treść spomiędzy znaczników. Ale tu należy pamiętać o jednej rzeczy, że tam również może zostać użyta składania wiki i inne tagi. Dlatego też zmienną $input należy jeszcze raz przepuścić przez parser za pomocą specjalnej funkcji:</p>
<pre class="brush: php">$output .= $parser-&gt;recursiveTagParse( $input, $frame );</pre>
<p>Argumentami tej funkcji jest treść do ponownego sparsowania oraz zmienna <em>$frame</em> którą otrzymaliśmy wcześniej jako czwarty argument funkcji <em>parsowanieRamka</em>. Gdy to już mamy możemy zamknąć blok i zwrócić gotowy kod html:</p>
<pre class="brush: php">$output .= '&lt;/div&gt;';
return $output;</pre>
<p>Pełny kod naszego rozszerzenia wygląda tak:</p>
<pre class="brush: php">&lt;?php
$wgHooks['ParserFirstCallInit'][] = 'mojParser';

function mojParser( &amp;$parser ) {
   $parser-&gt;setHook( 'ramka', 'parsowanieRamka');
   return true;
}

function parsowanieRamka( $input, $args, $parser, $frame ) {
   if(!empty($args['grafika'])){
      $file = wfFindFile($args['grafika']);
      $url = $file-&gt;getFullUrl();
   }
   $output = '&lt;div class="ramka" style="background-image: url('.$url.');"&gt;';
   $output .= $parser-&gt;recursiveTagParse( $input, $frame );
   $output .= '&lt;/div&gt;';
   return $output;
}
?&gt;</pre>
<h1>Nieco więcej o parsowaniu</h1>
<p>W powyższym przykładowym rozszerzeniu użyliśmy funkcji $parser-&gt;recursiveTagParse();. Jak już pisałem służy ona do tego by sparsować składnię wiki i dodatkowe tagi wewnątrz jakiegoś tekstu. Należy jednak pamiętać, że nie zostaną wtedy podmienione podpisy (~~~~). Tym zajmuję się tzw parser wstępny ale on także w tym wypadku nam nie pomoże. Jest to związane z tym, że tekst wewnątrz tagów dodawanych przez rozszerzenia jest parsowany przy każdym wyświetleniu strony na nowo a w bazie danych ląduje niezmieniony. Z tego też powodu własne tagi nie sprawdzą się w miejscach gdzie użytkownicy będą się podpisywać za pomoca 4 tyld.</p>
<p>Inną sprawą jest to, że należy uważać by nie parsować znaczników html które nie działają na stronach MediaWiki. Np. próba sparsowania tekstu <em>&lt;img src=&#8221;adres.png&#8221;&gt; </em>spowoduje, że ten kod pojawi się na stronie w formie tekstu a nie obrazka. Można jednak bezpiecznie parsować kod obrazka zapisany w wikiskładni tzn <em>[[Grafika:Plik.png]]</em>. Identyczna sytuacja zachodzi przy odnośnikach. Dlatego należy uważać by nie wrzucać do parsera przypadkowego kodu html a jedynie parsować to co można.</p>
<h1>Inny przykład: tag &lt;cytat&gt;</h1>
<p>Na koniec zamieszczę jeszcze jeden kod parsowania tagu. Jego składnia wygląda tak:<em> &lt;cytat autor=&#8221;Imię Nazwisko&#8221;&gt;&lt;/cytat&gt;</em> a skrypt który go parsuje przedstawia się następująco:</p>
<pre class="brush: php">function parsowanieCytat($input, $args, $parser, $frame ) {
   $output = '&lt;blockquote&gt;'.$input.'&lt;div&gt;'.$args['autor'].'&lt;/div&gt;&lt;/blockquote&gt;&lt;br style="clear: left;" /&gt;';
   return $parser-&gt;recursiveTagParse( $output, $frame );
}</pre>
<p>Do tego dochodzi jeszcze krótki kod CSS:</p>
<pre class="brush: css">blockquote{
  padding-left: 50px;
  background: url('quote.png') left 5px no-repeat;
  margin: 0px 20px 10px 0px;
  font-family: Georgia;
  font-style: italic;
  min-height: 27px;
  float: left;
  color: #333;
  max-width: 500px;
}
blockquote div{
  text-align: right;
  color: #666;
  font-style: normal;
  font-size: 10px;
  font-family: Arial;
  margin-right: 10px;
}</pre>
<p>Całość w akcji można zobaczyć na górze<a title="Dodatkowy tag Cytat w akcji" href="http://borealis.net.pl/index.php/Zombine"> tej strony</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/09/dodawanie-tagow-do-mediawiki/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Baner z ilością artykułów w MediaWiki</title>
		<link>http://mgdevelop.pl/index.php/2010/07/baner-z-iloscia-artykulow-w-mediawiki/</link>
		<comments>http://mgdevelop.pl/index.php/2010/07/baner-z-iloscia-artykulow-w-mediawiki/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 15:59:49 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[MediaWiki]]></category>
		<category><![CDATA[artykuły]]></category>
		<category><![CDATA[baza danych]]></category>
		<category><![CDATA[php GD]]></category>
		<category><![CDATA[reklama]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=431</guid>
		<description><![CDATA[O świetności danej encyklopedii internetowej świadczy ilość i jakość znajdujących się tam artykułów. Dlatego nie ma powodu by wstydzić się... <a href="http://mgdevelop.pl/index.php/2010/07/baner-z-iloscia-artykulow-w-mediawiki/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>O świetności danej encyklopedii internetowej świadczy ilość i jakość znajdujących się tam artykułów. Dlatego nie ma powodu by wstydzić się numerka reprezentującego ile jest stron w naszej wiki. Przeciwnie! Należy się z tym obnosić. A jeszcze lepiej jak robią to nasi użytkownicy. Dlatego w tym poradniku nauczymy się tworzyć dynamiczny obrazkowy banerek, na którym będzie wypisana ilość artykułów na naszej stronie w MediaWiki.</p>
<h1><span id="more-431"></span>Nasze miejsce pracy</h1>
<p>Dla naszych banerków najlepiej przygotować osobny folder. W nim umieśćmy obrazek który będzie podstawą naszego dzieła. Ja dla banerka mojej encyklopedii o grach firmy Valve  przygotowałem coś takiego:</p>
<p><a href="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/07/dynamicsignature1.png"><img class="alignnone size-full wp-image-434" title="dynamicsignature1" src="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/07/dynamicsignature1.png" alt="" width="468" height="60" /></a></p>
<p>Plan jest taki aby pod tytułem strony znajdował się napis <em>n artykuły(ów) o grach Valve</em> gdzie n jest oczywiście liczbą stron. Przed napisaniem tego skryptu musimy jednak zadbać jeszcze o jedną rzecz. Nasz baner będzie generowany w PHP przy każdym zapytaniu. Link do naszego obrazka nie może być jednak linkiem do pliku php, gdyż wtedy nie będzie się wyświetlał w podpisach na forach internetowych. Musimy skorzystać z możliwości jakie daje nam plik <em>.htaccess. </em>Po utworzeniu go w folderze z naszym banerem umieszczaniu w nim poniższy kod:</p>
<pre class="brush:shell">RewriteEngine On
RewriteRule ^baner.png$ generator.php [L]</pre>
<p>Ta instrukcja spowoduje, że chociaż adres będzie prowadził do pliku baner.png to serwer będzie zwracał treść z pliku generator.php.</p>
<h1>Generowanie obrazka</h1>
<p>Teraz możemy przystąpić do pisania skryptu PHP. Tworzymy więc nasz plik generator.php i na samym jego początku łączymy się z bazą naszej wiki</p>
<pre class="brush:php">$serverdb='localhost'; //adres serwera bazy danych
$dbuser='user'; //uzytkownik bazy danych
$dbuserpass='password'; //haslo uzytkownika
$db='database'; //nazwa bazy danych

$link = mysql_connect ($serverdb, $dbuser, $dbuserpass)
   or die (mysql_error());
mysql_select_db ($db);</pre>
<p>Gdy jesteśmy już połączeni z bazą możemy pobrać informacje o ilości artykułów. Wyciągniemy ta informację ze specjalnych tabel gdzie są przechowywane tego typu statystyki.</p>
<pre class="brush: js">$uchwyt = mysql_query ('SELECT ss_good_articles from wiki_site_stats');
$rekord = mysql_fetch_array($uchwyt);
$ilosc = $rekord['ss_good_articles'];</pre>
<p>Teraz, gdy ilość artykułów mamy już w w zmiennej <em>$ilosc</em> możemy napisać część kodu, która odmieni wyraz <em>artykuły</em> na potrzeby naszego napisu i złoży cały tekst w całość.</p>
<pre class="brush: js">$jednostki = substr($ilosc, strlen($ilosc)-1, 1);
if($jednostki == 2 || $jednostki == 3 || $jednostki == 4) $art = 'arykuły';
   else $art = 'arykułów';
$tekst = "$ilosc $art o grach Valve";</pre>
<p>Gdy to już mamy gotowe nic nie stoi na przeszkodzie by rozpocząć generowanie grafiki.</p>
<pre class="brush: js">$image = imagecreatefrompng("baner.png");
$black = imagecolorallocate($image, 0, 0, 0);
imagettftext($image, 10, 0, 250, 45, $black, 'calibri.ttf', $tekst);</pre>
<p>Podany kod kolejno wczytuje obrazek <em>baner.png</em>, tworzy indeks koloru czarnego i na końcu nakłada tekst na załadowaną grafikę. Użyta przy ostatniej operacji funkcja imagettftext przyjmuje kolejno jako argumenty zmienną z obrazkiem, rozmiar czcionki, pochylenie fontu w stopniach, współrzędne umieszczenia napisu, link do pliku z czcionką oraz na końcu treść napisu. W tym przykładzie użyliśmy czcionki <em>calibri.ttf, </em>której plik należy również umieścić w folderze z banerem.</p>
<h1>W stronę przeglądarki</h1>
<p>Aktualnie w zmiennej <em>$image</em> przechowujemy gotowy obrazek. Przed jego wyświetleniem musimy jednak zamienić co najmniej jedną informację w nagłówku wysyłanym do przeglądarki. Wersja minimalistyczna kodu odpowiedzialnego za wyświetlanie baneru wygląda tak:</p>
<pre class="brush: js">header("Content-type: image/jpeg");
imagejpeg($image);</pre>
<p>W tym przypadku informujemy tylko, że przesyłana treść jest grafiką, a nie tekstem jak wskazywałoby jego pochodzenie z pliku .php. Później przesyłamy sam obrazek. Jeśli zaś chcemy aby informacje wyświetlane na banerze były zawsze aktualne, musimy wymusić na przeglądarce by za każdym razem na nowo go pobierała z serwera. Użyjemy do tego tricku polegającego na wyłączeniu cachowania grafiki oraz ustawieniu przeszłej daty wygaśnięcia jej ważności.</p>
<pre class="brush: js">header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Content-type: image/jpeg");
imagejpeg($image);</pre>
<h1>Podsumowanie</h1>
<p>Oto gotowy efekt nasze pracy:</p>
<p><a href="http://www.borealis.x-12.pl"><img class=" alignnone" title="Baner Borealis" src="http://borealis.net.pl/dynamic/combine/baner.png" alt="Baner Borealis" /></a></p>
<p>Fajnie wygląda i co najważniejsze spełnia swoje zadania. Należy jednak pamiętać by nie nadużywać opcji wyłączania cachowania przy dużych serwisach by nie obciążyć bazy danych. A przy naprawdę dużych encyklopediach internetowych zalecane jest napisanie skryptu cachującego liczbę artykułów.</p>
<p>Na koniec załączam <a title="Pliki baneru" href="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/07/banermediawiki.zip">paczkę z wszystkimi plikami powyższego baneru</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/07/baner-z-iloscia-artykulow-w-mediawiki/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

