<?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>m1chu.eu - another devblog &#187; WordPress</title>
	<atom:link href="http://m1chu.eu/category/aplikacje-internetowe/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>http://m1chu.eu</link>
	<description>we live, as we dream... alone - another devblog</description>
	<lastBuildDate>Fri, 25 Jun 2010 22:04:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Jak wyizolować liczbę subskrybentów RSS korzystając z FeedBurner&#8217;a?</title>
		<link>http://m1chu.eu/2009/02/15/jak-wyizolowac-liczbe-subskrybentow-rss-korzystajac-z-feedburnera/</link>
		<comments>http://m1chu.eu/2009/02/15/jak-wyizolowac-liczbe-subskrybentow-rss-korzystajac-z-feedburnera/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 12:55:53 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webhosting]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[easy feed counter]]></category>
		<category><![CDATA[feedburner]]></category>
		<category><![CDATA[feedcount]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[repozytorium]]></category>
		<category><![CDATA[simplexmlelement]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://m1chu.eu/?p=1237</guid>
		<description><![CDATA[
W niezbędniku prawie każdego blogera leży możliwość menadżerowania swoimi kanałami RSS, bądź Atom. Któż z nas nie zna FeedBurner&#8217;a?. Zestawu narzędzi ułatwiających nam, czy to udostępnianie użytkownikom możliwości subskrypcji treści naszej strony, czy po prostu możliwość przejrzenia lub zamieszczenia statystyk w naszym serwisie. Pomimo dostarczonego API nie znajdziemy jednak bezpośrednio w panelu FeedBurner&#8217;a kodu pozwalającego [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="iborder" src="http://farm4.static.flickr.com/3316/3276810158_fd2d4b8829_o.png" alt="Pobieramy liczbę subskrybentów RSS poprzez FeedBurner" style="height: 119px;" /></p>
<p>W niezbędniku prawie każdego blogera leży możliwość menadżerowania swoimi kanałami RSS, bądź Atom. Któż z nas nie zna <strong>FeedBurner&#8217;a</strong>?. Zestawu narzędzi ułatwiających nam, czy to udostępnianie użytkownikom możliwości subskrypcji treści naszej strony, czy po prostu możliwość przejrzenia lub zamieszczenia statystyk w naszym serwisie. Pomimo dostarczonego API nie znajdziemy jednak bezpośrednio w panelu <strong>FeedBurner&#8217;a</strong> kodu pozwalającego na umieszczenie samej liczby subskrybentów bloga. I rozwiązanie tego, pozornie błahego problemu postaram się Wam dziś przedstawić&#8230;<br />
<span id="more-1237"></span></p>
<h2>Stary, dobry FeedBurner.com&#8230;</h2>
<p>Niespełna dwa lata temu słynny serwis zajmujący się obsługą kanałów RSS został przejęty za sto milionów dolarów przez <strong>Google</strong>. Pomimo tego, że minęło aż tyle czasu wielu blogerów nadal korzysta z zasobów starego, wysłużonego, pierwotnego FeedBurner&#8217;a. I co może wydawać się dziwne, to właśnie oni mają najbardziej ułatwioną sytuację.</p>
<p>Zarówno stara, jak i nowa odsłona serwisu oferują usługę <strong>FeedCount</strong> dostępną z poziomu menu <strong>Publicize</strong>. Pozwala ona na dobranie typu wbudowanego tła wyświetlającego ilość subskrybentów (statyczne, bądź animowane) oraz na dobranie jego barwy i koloru tekstu. Wraz z ustawieniem tych parametrów otrzymujemy kod HTML do wstawienia na naszą stronę. I tu rodzi się problem. Prócz kilku stylistycznych zmian wygląd tychże &#8220;chickletów&#8221; jest zawsze taki sam i najczęściej nijak pasuje do designu naszego bloga. Co zrobić jeżeli np. chcemy wraz z tekstem przycisku odnoszącego użytkowników do wygenerowanego kanału wstawić także ilość osób śledzących naszą stronę?</p>
<p>Rozwiązanie zaprezentuje na podstawie użytkowania platformy <a target="_blank" href="http://wordpress.org/"  title="Wordpress">Wordpress</a> (oczywiście ilość subskrybentów &#8211; opierając się na dalszym tekście &#8211; można zamieścić w każdym innym systemie zarządzania treścią, bądź nawet na własnej, prywatnej stronie). W takim wypadku wystarczy zainteresować się wtyczkami <a target="_blank" href="http://utnij.eu/5b5/"  title="FeedBurner FeedSmith 2.3">FeedSmith 2.3</a> (<a target="_blank" href="http://utnij.eu/632cd7/"  title="FeedBurner FeedSmith 2.3 PL">polska wersja</a>) (wg. developerów Wordpress&#8217;a kompatybilną ze wszystkimi wersjami 2.x) i <a target="_blank" href="http://utnij.eu/feed-count-plugin/"  title="Feed Count 1.2">Feed Count 1.2</a> (<a target="_blank" href="http://utnij.eu/776e/"  title="Feed Count 1.2 PL">polska wersja</a>). Pierwsza z nich niezbędna jest do obsługi kanału RSS przez serwis FeedBurner. </p>
<p>Jej instalacja oraz rejestracja w serwisie jest niezbędna do działania drugiej z nich. Jak wykonuje się instalacje wtyczek? Wystarczy wyodrębnić z archiwum odpowiednie pliki (w naszym pierwszym przypadku będzie to <strong>FeedBurner_FeedSmith_Plugin.php</strong>, w drugim <strong>feedcount.php</strong>) i umieścić je w katalogu <strong>wp-content/plugins/</strong> systemu Wordpress. Następnie wtyczki należy zaktywować w panelu administratora (<strong>Wtyczki / Nazwa wtyczki / Włącz</strong>).</p>
<p>Obydwa pluginy należy dodatkowo skonfigurować w zakładce <strong>Ustawienia</strong>. Pierwszy z nich swoje opcje ukrywa w podmenu <strong>FeedBurner</strong>. Zobaczycie tam dwa pola do uzupełnienia, jedno wymagane, drugie opcjonalne. Pierwsze z nich to pełny odnośnik do feedu strony w serwisie FeedBurner (i dla starej odsłony, i dla nowej na serwerach Google), a drugi to link do kanału RSS komentarzy.</p>
<p style="text-align: center; font-size: 10px;"><img class="iborder" src="http://farm4.static.flickr.com/3325/3278708424_d49400bae8_o.png" alt="Konfiguracja wtyczki FeedSmith w panelu" style="height: 280px;" /><br />Konfiguracja wtyczki FeedSmith w panelu.</p>
<p>Co do drugiego rozszerzenia to działa ono dla wersji <strong>2.x</strong> Wordpress&#8217;a, z tymże przy najnowszej <strong>2.7x</strong> może sprawiać problemy natury zwracania wyniku w postaci <strong>N/A</strong> zamiast poprawnej wartości.</p>
<p style="text-align: center; font-size: 10px;"><img class="iborder" src="http://farm4.static.flickr.com/3447/3277035819_12a3295a07_o.png" alt="Konfiguracja wtyczki Feed Count w panelu" style="height: 280px;" /><br />Konfiguracja wtyczki Feed Count w panelu.</p>
<p>Rozszerzenie to także należy dodatkowo skonfigurować. Robimy to w panelu poprzez menu <strong>Ustawienia / Feed Count</strong>. W jej opcjach trzeba podać co najmniej adres kanału (<em>Feed Url</em>) w postaci nazwy kanału na <strong>FeedBurner&#8217;ze</strong>, częstość aktualizowania ilości subskrybentów (<em>Update interval</em>) oraz częstość aktualizacji po wystąpieniu błędu (<em>Update interval (recovery)</em>). Pozostałe pola nie są wymagane. <em>Link url</em> to adres odnośnika pojawiającego się na zwróconej przez skrypt ilości osób śledzących stronę. <em>Before</em> za to jest treścią pojawiającą się przed liczbą w.w. użytkowników, a <em>After</em> to treść po.</p>
<p>Po wykonaniu konfiguracji należy jeszcze w strukturze szablonu strony dodać odpowiedni kod.</p>
<pre class="brush: php;">&lt;?php if (function_exists('fc_feedcount')) fc_feedcount(); ?&gt;</pre>
<p>Wstawić go musimy w miejscu w którym chcemy wyświetlać wystylizowaną liczbę użytkowników RSS (plugin ten nie zwraca tylko liczby otaczając ją poprzez dodatkowe tagi HTML). Oczywiście możemy go modyfikować. Jeżeli chcielibyście np. wyświetlić go w odnośniku (w <strong>header.php</strong>) o nazwie <strong>RSS</strong> w dodatkowych nawiasach to możecie to zrobić w następujący sposób:</p>
<pre class="brush: php;">&lt;?php
if (function_exists('fc_feedcount'))
{
	print ' (' . fc_feedcount() . ')';
}
?&gt;</pre>
<p>No i ostatecznie musicie w panelu <strong>FeedBurner&#8217;a</strong> (nie wtyczki, a profilu w serwisie w którym zakładaliście konto) zezwolić wtyczce na działanie z API tegoż serwisu. Wystarczy wejść do zakładki <strong>Publicize</strong>, a następnie do menu <strong>Awareness API</strong> i zaktywować tą funkcjonalność.</p>
<h2>Wtyczka Feed Count 1.2 dla Google FeedBurner!</h2>
<p>Jeżeli zdecydowaliście się jednak na migracje z starych serwerów serwisu, na ultraszybkie i megafajne klastry Google, a wcześniej trafnie stosowaliście w.w. metodę do wyodrębniania liczby użytkowników to prawdopodobnie będzie ona także działać po przejściu na <a target="_blank" href="http://feedburner.google.com/"  title="Google FeedBurner">feedburner.google.com</a>.</p>
<p>Trzeba jednak w takim wypadku dokonać pewnych, małych zmian w kodzie wyżej opisywanej wtyczki <strong>Feed Count</strong>. W tym celu edytujemy plik <strong>feedcount.php</strong> (np. poprzez <strong>Notepad++</strong> lub <strong>ZendStudio</strong>). Przechodzimy w okolice <strong>41</strong> linii w celu odnalezienia następującego kodu.</p>
<pre class="brush: php;">		  'map_fc_queryurl' =&gt;'http://api.feedburner.com/awareness/1.0/GetFeedData?uri=',</pre>
<p>Co można zauważyć element tablicy o nazwie przed <code>=></code> wskazuje na adres dostępowy do API, ale <em>feedburner.com</em>. A my przecież chcemy korzystać już z API Google. W tym celu należy tą linijkę zmienić niżej wymienionym kodem, po czym zapisać plik i ponownie wysłać go na serwer.</p>
<pre class="brush: php;">		  'map_fc_queryurl' =&gt;'https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=',</pre>
<h2>C&#8230; bombki strzelił! Jedyne co otrzymuje w wyniku to ten niewdzięczny &#8220;N/A&#8221;&#8230;</h2>
<p>Po pierwsze musicie sprawdzić czy biblioteka <a target="_blank" href="http://utnij.eu/curl-wiki/"  title="cURL Wiki">cURL (Client URL Library Functions)</a> jest dostępna w konfiguracjach Waszych serwerów (jako pakiet PHP). W tym celu wystarczy stworzyć jakikolwiek plik o rozszerzeniu <strong>.php</strong>, wypełnić go poniższym kodem i wywołać na hipotetycznie problematycznym serwerze.</p>
<pre class="brush: php;">&lt;?php
phpinfo();
?&gt;</pre>
<p>W wylistowanych wynikach wystarczy poszukać wpisu <strong>cURL support</strong> i sprawdzić, czy jego flaga ustawiona jest na <strong>enabled</strong>. Jeżeli nie, to właśnie znaleźliście przyczynę problemu. Powyższa, kluczowa dla nas wtyczka oparta jest na tym libie, a co za tym idzie jego brak powoduje niemożność poprawnego wykonania kodu tego rozszerzenia.</p>
<h2>Diagnoza problemu: cURL&#8230;</h2>
<p>Kiedy zawodzą dostępne już rozwiązania najlepszym sposobem na pozbycie się własnego problemu jest&#8230; napisanie indywidualnej solucji. Niestety to wiążę się najczęściej z jedną z dwóch rzeczy. Albo z posiadaniem konkretnej wiedzy odnośnie danego problemu, albo z wydatkiem związanym z opłaceniem osoby która rozwiąże Waszą dolegliwość.</p>
<p>Jeżeli dotarliście do tego punktu tzn. że nadal nie uzyskaliście pożądanego efektu. Pora więc właśnie na w.w. sposób, z tymże ja dla Was przygotuję go w stu procentach&#8230; za friko :] Mógłbym Wam zaprezentować kilkulinijkowy sposób, bo praktycznie do tego ogranicza się rozwiązanie &#8211; pytanie po co? Blog ten ma uczyć, dlatego postaram się Wam przedstawić dwie metody pobierania potrzebnych nam danych które po lekkim tuningu złożą się w jedną, w pełni funkcjonalną wtyczkę napisaną specjalnie na potrzeby tego artykułu. I w gruncie rzeczy będzie to najbardziej optymalne rozwiązanie ze wszystkich tutaj przedstawionych&#8230;</p>
<p>Przypadek numer jeden: <strong>brak możności użytkowania cURL&#8217;a</strong>. Jak to w życiu bywa, jak nie da wejść się jednym oknem, trzeba próbować drugim. Sposobów jest wiele, ja wybiorę użycie funkcji <a target="_blank" href="http://pl.php.net/file_get_contents"  title="file_get_contents - php.net">file_get_contents</a>. Zaimplementowana jest ona w PHP od wersji <strong>4.3</strong> i dodatkowo do jej działania konfiguracja serwera musi zezwalać na zdalne (z zewnętrznych źródeł) pobieranie plików. Trik który zastosujemy ogranicza się kolejno do:</p>
<ul>
<li>pobrania danych z adresu FeedBurner&#8217;a korzystając z udostępnionego przez niego API,</li>
<li>sprawdzenia czy odebrane dane są poprawne (pod kątem poprawności adresu i ewentualnych wyjątków),</li>
<li>wyszukanie frazy <code>circulation="</code> w posiadanym buforze. Kod który pobraliśmy wcześniej <strong>musi</strong> być w formacie XML, a co za tym idzie składa się on ze znaczników i parametrów. Właśnie parametr <code>circulation</code> zawiera w sobie wartość będącą ilością subskrybentów,</li>
<li>jeżeli fraza nie zostanie znaleziona, zwrócenie błędu,</li>
<li>w przeciwnym razie pobranie ciągu od pozycji wyszukiwanej wyżej frazy + 13 znaków (długość szukanego słowa), aż do znalezienia następnego cudzysłowia (bez niego).</li>
</ul>
<pre class="brush: php;">&lt;?php
$buffer = file_get_contents(ADRES_SERWER . NAZWA_KANALU); // pobranie pliku
if ( $buffer === false ) // zwrócenie błędu
{
	print 'n/d';
}

$pre_position = strpos($buffer, 'circulation=&quot;'); // wyszukanie pozycji frazy z drugiego argumentu
if ( $pre_position === false ) // w wypadku nieodnalezienia zwrócenie błędu (niepoprawny plik)
{
	print 'n/d';
}
else {
	print substr($buffer, ($pre_position+13), strpos($buffer, '&quot;', ($pre_position+14)) - ($pre_position+13)); // &quot;wypisanie na ekran&quot; zawartości parametru &quot;circulation&quot; z pobranego pliku XML
}
?&gt;</pre>
<h2>Kiedy problemem nie jest jednak cURL&#8230;</h2>
<div class="explain"><code>SimpleXMLElement</code> &#8211; klasa rozszerzenia <code>SimpleXML</code> dostarczająca prosty zestaw narzędzi do konwersji XML na obiekt na którym można operować poprzez użycie selektorów.</p>
<p>Przykład:</p>
<pre class="brush: xml;">&lt;parent&gt;
	&lt;children&gt;raz&lt;/children&gt;
	&lt;children&gt;dwa&lt;/children&gt;
&lt;/parent&gt;</pre>
<pre class="brush: php;">$xml = new SimpleXMLElement(XML);
$found = $xml-&gt;xpath('parent/children'); // wyszukiwanie potomka w drzewie dokumentu XML (argument w postaci np. rodzic/potomek/potomek_potomka/itp.)
print_r($found); // wypisanie tablicy wyników</pre>
</div>
<p>Plugin <strong>FeedCount</strong> nie zawsze działa na Wordpress&#8217;ie <strong>2.7x</strong>. Nie pytajcie dlaczego. Szczerze? Nie wiem i nie chciało mi się dociekać co jest tego powodem. Postanowiłem jakiś czas temu spotykając się z tą przypadłością po prostu stworzyć bardziej uproszczony kod, niż ten z popularnej wtyczki. Jak wygląda jego schemat krokowy? Po kolei:</p>
<ul>
<li>inicjalizacja cURL,</li>
<li>ustawienie opcji transferu biblioteki (zwracanie zawartości bez wypisywania jej na ekran oraz wprowadzenie adresu docelowego),</li>
<li>wykonanie zadania, po czym zniszczenie sesji połączenia,</li>
<li>sprawdzenie, czy nie występuje znacznik nadrzędny <code>err</code> z parametrem <code>code</code> o wartości <strong>1</strong> (oznaka zwrócenia błędu, najczęściej nieodnalezienia pliku),</li>
<li>jeżeli powyższy punkt nie okaże się prawdą to utworzenie obiektu <a target="_blank" href="http://pl.php.net/simplexml"  title="SimpleXML - php.net"><code>SimpleXMLElement</code></a> i wyszukanie zawartości wyżej już wspomnianego atrybutu <code>circulation</code>.</li>
</ul>
<pre class="brush: php;">&lt;?php
$resource = curl_init(); // inicjalizacja
curl_setopt($resource, CURLOPT_RETURNTRANSFER, 1); // bez wypisania na ekran
curl_setopt($resource, CURLOPT_URL, ADRES_SERWER . NAZWA_KANALU); // przekazanie adresu do pobrania
$buffer = curl_exec($resource); // wykonanie
curl_close($resource); // zamknięcie sesji

$xml = new SimpleXMLElement($buffer); // obiekt analizy składni XML
if ( $xml-&gt;err['code'] == '1' ) // sprawdzenie wystąpienia błędu
{
	print 'n/d';
}
print $xml-&gt;feed-&gt;entry['circulation']; // pobranie ilości subskrybentów
?&gt;</pre>
<p>Aby bardziej wyjaśnić działanie powyższej partii kodu posłużę się przykładowymi danymi, jakie mogą zostać pobrane.</p>
<pre class="brush: xml;">&lt;rsp stat=&quot;ok&quot;&gt;
  &lt;!--This information is part of the FeedBurner Awareness API. If you want to hide this information, you may do so via your FeedBurner Account.--&gt;
  &lt;feed id=&quot;0ua2berteje16lsipgq0b8uk74&quot; uri=&quot;worldclub-pl&quot;&gt;
    &lt;entry date=&quot;2009-02-13&quot; circulation=&quot;1&quot; hits=&quot;2&quot; downloads=&quot;0&quot; reach=&quot;0&quot; /&gt;
  &lt;/feed&gt;
&lt;/rsp&gt;</pre>
<p>Można z niego wywnioskować, że odpowiednio operując na klasie <code>SimpleXMLElement</code> moglibyśmy uzyskać identyfikator konta, jego część adresu zwaną w tym artykule po prostu nazwą, datę utworzenia, ilość osób śledzących RSS&#8217;a, liczbę kliknięć oraz ściągnięć. Działanie powyższej klasy jest proste. Z kodu XML tworzymy obiekt po którym możemy przesuwać się za pomocą zwyczajnych selektorów. Przykładowo jeżeli chcielibyśmy wyłuskać z powyższego przykładu identyfikator (<code>id</code>) zrobilibyśmy to w następujący sposób:</p>
<pre class="brush: php;">print $xml-&gt;feed['id'];</pre>
<p>Pierwszy, główny element <code>rsp</code> jest pomijany w instancji obiektu.</p>
<p style="text-align: center; font-size: 10px;"><img class="iborder" src="http://farm4.static.flickr.com/3601/3279482457_2255ac2de9_o.png" alt="Zasada działania SimpleXMLElement na podstawie kodu pobierania liczby subskrybentów" style="height: 230px;" /><br />Zasada działania SimpleXMLElement na podstawie kodu pobierania liczby subskrybentów.</p>
<h2>Autorska wtyczka finalnym rozwiązaniem naszego problemu!</h2>
<p>I tak oto dochodząc do meritum przedstawiam Wam rozszerzenie uproszczone, ale za to bardziej wzbogacone o trzy, moim zdaniem niezbędne funkcjonalności. <a href="http://dev.m1chu.eu/index.php?title=Easy_Feed_Counter"  title="Easy Feed Counter"><strong>Easy Feed Counter</strong></a> posiada możliwość łatwej instalacji i konfiguracji poprzez panel administratora. Proces wdrażania tego pluginu jest adekwatny do dodawania opisywanego wcześniej <strong>FeedCount</strong> (jest także dokładnie opisany w linku powyżej w repozytorium modyfikacji). Pozwala on na ustawienie serwera feedów, metody pobierania statystyk oraz wpisanie nazwy konta kanału RSS na FeedBurner&#8217;ze. Opcjonalnie możecie także dodać konto komentarzy na tym serwisie, o ile takowe posiadacie.</p>
<p style="text-align: center; font-size: 10px;"><img class="iborder" src="http://farm4.static.flickr.com/3302/3279600765_6edbcf3db2_o.png" alt="Rezultaty działania wtyczki" style="height: 171px;" /><br />Rezultaty działania wtyczki.</p>
<p>Rozwiązanie to ma także jeden wielki, dodatkowy atut. Nie formatuje jak inne pluginy zwracanej treści, a ogranicza się do podania wartości (liczby użytkowników), bądź kodu błędu (<strong>n/d</strong>). To pozwala na szersze modyfikacje położenia bądź wyglądu wyników po wywołaniu funkcji <code>easyfeedcounter_get([opcjonalny: parametr])</code> bez dodatkowej ingerencji w sam kod rozszerzenia.</p>
<pre class="brush: php;">&lt;?php
if (function_exists('easyfeedcounter_get'))
{
	$subscribers = easyfeedcounter_get(1); // argument o wartości 1 wskazuje wtyczce, że ma zwrócić dane dotyczące komentarzy
	if ( is_numeric($subscribers) !== false ) // brak błędów
	{
		print $subscribers . ' osób subskrybuje aktualnie Twoje komentarze!';
	}
}
?&gt;</pre>
<p>Bardziej skrupulatne objaśnienie, opisane krok po kroku znajdziecie w moim <a href="http://dev.m1chu.eu/index.php?title=Easy_Feed_Counter"  title="Easy Feed Counter">repozytorium</a>. W przypadku wątpliwości dotyczących tematu, bądź instalacji tego tworu proszę śmiało pytać :]</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2009/02/15/jak-wyizolowac-liczbe-subskrybentow-rss-korzystajac-z-feedburnera/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Kolizje współdziałania bibliotek JavaScript na podstawie wtyczek WordPress&#8230;</title>
		<link>http://m1chu.eu/2008/10/02/kolizje-wspoldzialania-bibliotek-javascript-na-podstawie-wtyczek-wordpress/</link>
		<comments>http://m1chu.eu/2008/10/02/kolizje-wspoldzialania-bibliotek-javascript-na-podstawie-wtyczek-wordpress/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 10:45:38 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Prototype]]></category>
		<category><![CDATA[Webhosting]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[biblioteka]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[wtyczka]]></category>

		<guid isPermaLink="false">http://m1chu.eu/?p=96</guid>
		<description><![CDATA[
Coraz więcej różnorodnych stron internetowych korzysta z techniki która w szeroki sposób pozwoliła rozwinąć się przede wszystkim JavaScriptowi &#8211; z Ajaxa. Podobnie jest z różnorodnymi wtyczkami do systemu blogów WordPress. Z reguły korzystają one jednak z jakiejś biblioteki JavaScript zbierającej w całość jego najważniejsze funkcje i pozwalającej na ich prostsze użycie. W momencie jednak, kiedy [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="iborder" src="http://farm4.static.flickr.com/3066/2953934393_d684ed0058_o.png" alt="Współdziałanie framework'ów na przykładzie WordPress'a" /></p>
<p>Coraz więcej różnorodnych stron internetowych korzysta z techniki która w szeroki sposób pozwoliła rozwinąć się przede wszystkim JavaScriptowi &#8211; z Ajaxa. Podobnie jest z różnorodnymi wtyczkami do systemu blogów <a target="_blank" href="http://wordpress.org/"  title="WordPress">WordPress</a>. Z reguły korzystają one jednak z jakiejś biblioteki JavaScript zbierającej w całość jego najważniejsze funkcje i pozwalającej na ich prostsze użycie. W momencie jednak, kiedy w naszych pluginach pojawi się w użyciu kilka wtyczek możemy napotkać problem kolizji ich współdziałania.</p>
<p><span id="more-96"></span></p>
<h2>Prolog!</h2>
<p>Zanim zacznę muszę wspomnieć, że kolizja opisywana poniżej może występować na jakiejkolwiek stronie, a opisywana przeze mnie sytuacja jest tylko przykładem. Nie mniej jednak mankament ten postaram się wytłumaczyć na podstawie jednoczesnego działania <a target="_blank" href="http://utnij.eu/ajax-comments/"  title="WP Ajax Comments">AJAX Comments</a> i przystosowanej do personalnych potrzeb modyfikacji zakładek (przykładem są te umieszczone z lewej strony tego wpisu). Pierwsza wtyczka domyślnie używa <a target="_blank" href="http://script.aculo.us/"  title="Script.Aculo.Us">Script.Aculo.Us</a>, a co za tym idzie także frameworku <a target="_blank" href="http://www.prototypejs.org/"  title="Prototype">Prototype</a>. W drugim wypadku oprę się o <a target="_blank" href="http://vivee.info/2008/08/05/zakladki-do-sidebara/"  title="Zakładki do Sidebara">kurs tworzenia zakładek</a> w WP <strong>palmiaka</strong>, który używa za to <a target="_blank" href="http://jquery.com/"  title="jQuery">jQuery</a>.</p>
<p>Po poprawnej instalacji obydwu modyfikacji pewnie spora część z Was nie dostrzeże dręczącego nas feleru. Dlaczego? Gdyż na stronie głównej wszystko będzie działało prawidłowo, ale bynajmniej nie na podstronach w których będzie możliwe komentowanie wpisów. Dla przykładu w momencie wczytania najpierw <strong>prototype.js</strong> i <strong>scriptaculous.js</strong>, a później <strong>jquery.js</strong> stworzone przez nas zakładki nie będą poprawnie działać (nie zostaną one ukryte i nie będzie możliwości przejścia pomiędzy nimi). Dlaczego tak się dzieje? Tutaj należałoby poruszyć pewną sprawę dotyczącą samego działania frameworków tego typu.</p>
<h2>Funkcja $(argumenty)</h2>
<p>Między innymi do tworzenia obiektu danej biblioteki używa się funkcji <code>$(argumenty);</code>. Dzięki temu operujące np. na obiektach DOM, czy tablicach frameworki dzięki tej specjalnej konstrukcji pozwalają użytkownikowi na wykorzystywanie ich konkretnych funkcji.</p>
<p style="text-align: center;"><a target="_blank" href="http://farm4.static.flickr.com/3155/2905203185_36c209390b_o.png"  title="Powiększenie" class="lightbox"><img src="http://farm4.static.flickr.com/3155/2905203185_1e8236bb72.jpg" alt="Różnorodne metody korzystania z elementów strony" /></a></p>
<h2>Problematyka korzystania z więcej niż jednej biblioteki naraz&#8230;</h2>
<p>W momencie kiedy w skrypcie korzystamy z dwóch lub większej ilości frameworków może nastąpić kolizja w ich działaniu. W uproszczeniu przez użycie <code>$();</code> w każdej z nich. I tak to w naszym przykładzie funkcje, czy odwołania do obiektów które powinny być wykonane za pomocą <strong>jQuery</strong> zostaną wykonane przez pierwszą wczytaną klasę. A wszystko przez to, że każda z podanych bibliotek odwołuje się do danego elementu w taki sam sposób.</p>
<h2>Solucja!</h2>
<p>Na szczęście od wersji <strong>1.1.4</strong> z pomocą przychodzą nam developerzy <strong>jQuery</strong> wraz z funkcją pozwalającą na interoperacyjność &#8211; <code>jQuery.noConflict(param);</code>.</p>
<pre class="brush: jscript;">jQuery.noConflict(); // zwraca kontrolę nad $ bibliotece domyślnej (wcześniej używanej)
jQuery.noConflict(true); // zwraca kontrolę nad $ i jQuery (którego $ jest aliasem) oryginalnemu właścicielowi - należy używać z ostrożnością!</pre>
<p>Co należy wiedzieć w kwestii używania tego to przede wszystkim fakt, że wymaga się, aby powyższą funkcję wywołać przed użyciem elementów innych bibliotek, a także <strong>jQuery</strong> powinno być wczytywane po pozostałych frameworkach. W konkretnym wypadku związanym z WP który opisujemy należy także domyślnie dostarczone niżej wymienione biblioteki uaktualnić. Niestety w opisywanych tutaj wtyczkach i systemie blogów są to wersje starsze i przedstawiony trick w tym artykule nie zadziała dopóki nie ściągniemy zaktualizowanych wersji frameworków.</p>
<pre class="brush: jscript;">&lt;script type=&quot;text/javascript&quot; src=&quot;libs/prototype.js&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;libs/scriptaculous.js&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;libs/jquery.js&quot; /&gt;</pre>
<p>Domyślnie także należy używać w tym trybie <strong>jQuery</strong> zamiast <strong>$</strong>.</p>
<pre class="brush: jscript;">jQuery.noConflict();
jQuery(&quot;p&quot;).hide(); // użycie frameworka jQuery
$(&quot;div&quot;).style.display = 'none'; // użycie innego frameworka, np. prototype</pre>
<p>Ponieważ oczywiście zaprezentowana funkcja jest podatna na przypisywanie do zmiennych to niekoniecznie musimy używać standardowej, dłuższej nazwy. Negatywem tego rozwiązania jest jednak potencjalny konflikt nazw w przypadku pisania aplikacji internetowej przez wielu programistów.</p>
<pre class="brush: jscript;">var q = jQuery.noConflict();
q(&quot;p&quot;).hide();
$(&quot;div&quot;).style.display = 'none';</pre>
<p>Ostatecznie moglibyście także spytać <strong>&#8220;co zrobić, aby móc wewnątrz bloku kodu używać $ dla jQuery?&#8221;</strong>. Wystarczy poprzedzić zadaną funkcję przez <code>jQuery</code>, bądź zakończyć poprzez <code>(jQuery)</code>.</p>
<pre class="brush: jscript;">jQuery(function($) { [...] }); // wersja pierwsza
(function($) { [...] })(jQuery); // wersja druga</pre>
<p>Niestety w takim wypadku wewnątrz powyższych bloków kodu nie ma możliwości odniesienia się do obiektów innych bibliotek.</p>
<h2>Przykład pozwalający na prawidłowe działanie wspomnianych zakładek&#8230;</h2>
<p>Poprawiony przykład z <strong>vivee</strong>, który należy użyć w wypadku w.w. konfliktu (kod JavaScript).</p>
<pre class="brush: jscript;">jQuery.noConflict();

function tabs(id) {
	jQuery(&quot;#&quot;+id+&quot; h2:first a&quot;).addClass(&quot;active&quot;);
    jQuery(&quot;#&quot;+id+&quot; div&quot;).not(&quot;:first&quot;).hide();

    jQuery(&quot;#&quot;+id+&quot; h2 a&quot;).click(function() {
    	var licznik = jQuery(&quot;#&quot;+id+&quot; h2 *&quot;).index(this);                                             

        jQuery(&quot;#&quot;+id+&quot; h2 a&quot;).removeClass(&quot;active&quot;);
        jQuery(this).addClass(&quot;active&quot;);
        jQuery(&quot;#&quot;+id+&quot; div:visible&quot;).hide();

        jQuery(&quot;#&quot;+id+&quot; div&quot;).eq(licznik).show();
        return false;
    });
}

jQuery(document).ready(function(){
    tabs(&quot;zakladki&quot;);
});</pre>
<h2>Epilog&#8230;</h2>
<p><strong>WPNinja</strong> na swoim blogu poświęconym WordPressowi prawidłowo stwierdził w stosunku do mojej osoby, że mieszanie bibliotek nie jest dobrym zwyczajem.</p>
<pre class="brush: plain;">&quot;@m1chu,
Mieszanie ze sobą bibliotek to masakra. Nie dość, że zajmuje to niemiłosiernie dużo miejsca to, jak zauważyłeś w swoim artykule, może powodować konflikty.&quot;</pre>
<p>Opisany przeze mnie artykuł powinien być stosowany tylko w wyjątkowych sytuacjach. Należy z reguły <strong>unikać</strong> użytkowania kilku frameworków naraz, bo to obciąża w znacznym stopniu skrypt poprzez ich wagę, a co za tym idzie ilością danych do załadowania. Zdaję sobie jednak sprawę, że niekiedy jest to niezmiernie trudne (czego jak na razie w fazie rozwojowej przykładem jest mój blog ;]). Podziękowania za przypomnienie dla <strong>WPNinja&#8217;y</strong> o tym, że zapomniałem tak ważnego faktu umieścić w swoich wpisie.</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2008/10/02/kolizje-wspoldzialania-bibliotek-javascript-na-podstawie-wtyczek-wordpress/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Raz-Captcha (Wordpress anti-spambot plugin)</title>
		<link>http://m1chu.eu/2007/09/26/raz-captcha-wordpress-anti-spambot-plugin/</link>
		<comments>http://m1chu.eu/2007/09/26/raz-captcha-wordpress-anti-spambot-plugin/#comments</comments>
		<pubDate>Wed, 26 Sep 2007 19:07:46 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[Bugtrack]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[anti-spambot]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[raz-captcha]]></category>
		<category><![CDATA[token]]></category>

		<guid isPermaLink="false">http://m1chu.eu/informatyka/bugtrack/raz-captcha-wordpress-anti-spambot-plugin/</guid>
		<description><![CDATA[Kilka dni temu zauważyłem (co chyba na tego typu skryptach nie jest niczym niesamowitym) pełną ofensywę botów na stronie w postaci ich rejestracji. Z braku czasu dopiero dziś udało mi się wprowadzić kilka udoskonaleń które mam nadzieję, że pomogą w pozbyciu się zbędnych robotów.

Oczywiście z wyżej podanego powodu wprowadziłem gotowe rozwiązania, a mianowicie m.in. Raz-Captcha. [...]]]></description>
			<content:encoded><![CDATA[<p>Kilka dni temu zauważyłem (co chyba na tego typu skryptach nie jest niczym niesamowitym) pełną ofensywę botów na stronie w postaci ich rejestracji. Z braku czasu dopiero dziś udało mi się wprowadzić kilka udoskonaleń które mam nadzieję, że pomogą w pozbyciu się zbędnych robotów.</p>
<p><span id="more-19"></span></p>
<p>Oczywiście z wyżej podanego powodu wprowadziłem gotowe rozwiązania, a mianowicie m.in. <a href="http://raz-soft.com/display-english-posts-only/wordpress-plugin-login-register-anti-spambots-captcha/" title="Raz-Captcha" onclick="this.target='_blank'" >Raz-Captcha</a>. Część osób miało problem z systemem weryfikacji graficznej, które autor modyfikacji w dziwny sposób tłumaczył zerowaniem elementu <em>$_SESSION</em> odpowiedzialnego za przekazanie zahashowanej wartości wygenerowanego tokena, a druga część twierdziła, że mod działa (jakim sposobem nie wiem). Miałem podobny problem jak ta pierwsza grupa i dlatego postanowiłem przyjrzeć się problemowi ciut dokładniej.</p>
<p>Zakładam z góry, że nie jest to wina Wordpressa, czy zastosowanego stylu. Nie widzę powodu aby tak twierdzić, tym bardziej że z samego kodu który zanalizowałem wynika, że bug jest uzasadniony i dotyczy opcji silnika captcha dla <strong>PNG-phpBB3 8bit Grey</strong> i <strong>PNG-phpBB3 Advanced</strong>. I pomimo, że pomyłka jest naprawdę znikoma w sensie objętości to przysparza ona wielu problemów. W czym tkwi błąd?</p>
<p>Pozwolicie, że zanalizuje go na opcji <strong>PNG-phpBB3 8bit Grey</strong>, gdyż problem z drugim silnikiem jest adekwatny do tego, dotyczy tylko następnego warunku (<em>else if</em>) w pliku który zaraz omówię. Na początek należy otworzyć <strong>raz-captcha.php</strong> i około linijki <em>193</em> znaleźć:</p>
<pre class="brush: php;">else if ($option['rca_engine'] ==3) // phpBB3 no-gd bw png engine
{
	require_once(&quot;engines/phpbb-nogd.php&quot;);
	$captcha = new captcha();
	$password=gen_rand_string(mt_rand(5, 8));
	$captcha-&gt;execute($password, time());
	$_SESSION['raz_captcha_gen']=md5($password);
	exit();
}</pre>
<p>Kod ten odpowiada za inicjalizację funkcji, metod i przypisywanie zmiennych odpowiedzialnych za końcowe wyświetlenie tokena w opcji którą opisuję. I tutaj pojawia się błąd. Domyślnie autor modyfikacji najpierw odwołuje się do metody <em>execute</em>, a dopiero później przypisuje do danej sesji zahashowany wygenerowany token (dokładniej jego znaki).</p>
<pre class="brush: php;">$captcha-&gt;execute($password, time());
$_SESSION['raz_captcha_gen']=md5($password);</pre>
<p>Jeśli otworzymy teraz plik <strong>phpbb-nogd.php</strong> to około linijki <em>134</em> możemy zobaczyć, że po wykonaniu metody <strong>execute</strong> tej klasy i po wyświetleniu wyniku następuje brutalne zatrzymanie skryptu i wszystko co ma dziać się dalej np. w pliku <strong>raz-captcha.php</strong> zostaje przerwane.</p>
<pre class="brush: php;">	header('Content-Type: image/png');
	header('Cache-control: no-cache, no-store');
	echo $image;
	exit;
}</pre>
<p>I tu jest nasz bug. W pliku który otwieraliśmy na początku wystarczy zamienić linijkami wywołanie metody z przypisaniem do sesji naszego ciągu znaków, tak aby cały warunek wyglądał tak:</p>
<pre class="brush: php;">else if ($option['rca_engine'] ==3) // phpBB3 no-gd bw png engine
{
	require_once(&quot;engines/phpbb-nogd.php&quot;);
	$captcha = new captcha();
	$password=gen_rand_string(mt_rand(5, 8));
	$_SESSION['raz_captcha_gen']=md5($password);
	$captcha-&gt;execute($password, time());
	exit();
}</pre>
<p>Nasz problem powinien zniknąć. Adekwatnie na poniższym warunku możemy też poprawić błąd programisty.</p>
<pre class="brush: php;">else if ($option['rca_engine'] ==4) // phpBB3 Advanced
{ </pre>
<p>Zaznaczam, że problem testowany był na Wordpressie w wersji 2.2.3.</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2007/09/26/raz-captcha-wordpress-anti-spambot-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
