Blogrys

Czy Putin rozkaże użyć Atomu?

Nie wiem. Ale powinien. Bo oficjalna strona rządu rosyjskiego siedzi wciąż na przestarzałym RSS-ie. W wyścigu zbrojeń Blogrys właśnie osiągnął „technological edge”. Odtąd „missile gap”, czy raczej „feed gap”, będzie się tylko powiększał.

Gdy miesiąc temu pyszniłem się Comeconem, SpeX przytomnie zauważył, że poza mailowymi powiadomieniami przydałyby się także osobne kanały eresesowe agregujące komentarze pod poszczególnymi notkami. Zamówienie zrealizowane! Od dzisiaj nowy mechanizm będzie aktywny, a linki do feedów będą figurować zarówno w HTML-owych nagłówkach wpisów – do szybkiego przechwycenia przez czytnik – jak i na dole, w formularzu Comeconu, tuż nad polem służącym do mailowej prenumeraty.

Przy okazji zmieniłem format wszystkich Blogrysowych feedów z RSS na Atom. Przez ćwierć wieku używałem skrótowca RSS (Really Simple Syndication) jako synonimu powiadomień o nowościach na stronie internetowej. Nigdy nie zaprzątałem sobie głowy, co oznacza pojawiający się tu i ówdzie ukośnik „RSS / Atom”. Gdy kleciłem nowy silnik Blogrysu, przekleiłem po prostu pierwszy lepszy eresesowy feed z cudzej witryny i dostosowałem jego zawartość do własnych potrzeb, nie przejmując się specyfikacjami formatu.

Dopiero niedawno odkryłem, że Atom nie jest wcale wariantem RSS-a! Atom i RSS są hiponimami feedu1. Sprawę gmatwa szereg czynników:

  • Pierwsza wersja języka znacznikowego RSS (autorstwa Netscape’u) ujrzała światło dzienne już w 1999 r. stając się na pewien czas równoznaczna z szybkim informowaniem internautów o świeżej treści na interesujących witrynach.
  • W 2005 r. IETF zaproponowało format Atom jako spójniejszą, przemyślaną alternatywę dla RSS-a.
  • W 2009 r. pojawiła się najnowsza wersja RSS-a. Jednak mimo czteroletniej przewagi nad Atomem, RSS 2.0 nadal uważany jest przez ekspertów za rozwiązanie nieco gorsze, ponieważ pewne podstawowe błędy designerskie były już nie do usunięcia.
  • Zarówno RSS jak i Atom korzystają ze składni XML (podobnie jak XHTML, czyli odmiana HTML-a z dodatkowymi obostrzeniami) i na pierwszy rzut niewprawionego okna są nie do odróżnienia.
  • W języku polskim nie przyjął się odpowiednik słowa „feed” oznaczającego „spis nowości internetowych”2. Proponuję „paszka”.

Oddaję niniejszym w Wasze czytniki nową, zatomizowaną paszkę Blogrysa (URL nie uległ zmianie) oraz paszki z komentarzami (na przykład ). Feedy komentatorskie będą tworzone począwszy od dzisiejszego wpisu, chociaż wyobrażam sobie, że ktoś chciałby na wszelki wypadek rozpocząć atomową obserwację notek dawnych, na przykład tej najpopularniejszej sprzed dwunastu lat. Na otarcie łez proponuję więc alternatywny feed główny, w którym publikowane będą nowe notki w całości – to dla tych, którzy wolą czytać blogi bez uruchamiania przeglądarki – oraz feed z najnowszymi komentarzami.

Zerknijmy jeszcze na pehapową funkcję, która robi całą robotę:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function updateFeed($dateOfPost, $postTitle, $postURL, $commentTimestamp, $commenter, $commenterURL, $comment, $newestComments) {
    global $commentFeedsDir, $msg_commentFeedEntryTitle, $msg_commentInContext;
    $feedFilename = "comments_blogpost" . $dateOfPost . ".xml";
    $feedFilepath = $commentFeedsDir . "/" . $feedFilename;
    if (!file_exists($feedFilepath)) { return false; }
    $commentTimestamp = date("c", strtotime($commentTimestamp));
    $newEntry = <<<ENTRYENDS
    <entry>
    <title>$msg_commentFeedEntryTitle $postTitle</title>
    <author><name>$commenter</name><uri>$commenterURL</uri></author>
    <link rel="alternate" type="text/html" href="$postURL" />
    <id>$postTitle$commentTimestamp</id>
    <published>$commentTimestamp</published>
    <updated>$commentTimestamp</updated>
    <summary>$msg_commentInContext</summary>
    <content type="html"><![CDATA[$comment]]></content>
    </entry>
    </feed>
    ENTRYENDS;
    $feedContent = file_get_contents($feedFilepath);
    $feedContent = preg_replace('/^\s*<updated>.*$/m', "<updated>$commentTimestamp</updated>", $feedContent, 1);
    $feedContent = str_replace("</feed>", $newEntry, $feedContent);
    file_put_contents($feedFilepath, $feedContent);
    if ($newestComments) {
        $feedFilezpath = $commentFeedsDir . "/comments_newest.xml";
        if (!file_exists($feedFilepath)) { return false; }
        $feedContent = file_get_contents($feedFilepath);
        if (substr_count($feedContent, "<entry>") > 10) {
            $feedContent = preg_replace('/<entry>[\s\S]+?<\/entry>', "", $feedContent, 1);
        }
        $feedContent = preg_replace('/^\s*<updated>.*$/m', "<updated>$commentTimestamp</updated>", $feedContent, 1);
        $feedContent = str_replace("</feed>", $newEntry, $feedContent);
        file_put_contents($feedFilepath, $feedContent);
    }
    return true;
}

Pobrawszy ustawienia3 (L2) tworzymy nazwę pliku z feedem w oparciu o datę postu (L3) i sprawdzamy, czy plik leży na serwerze tam, gdzie powinien (L4-5). A powinien, bo został wygenerowany już w momencie publikacji wpisu. Następnie konwertujemy timestamp komentarza do XML-owego formatu (L6) i oplatamy komentarz Atomowymi znacznikami (L7-19). Magiczne CDATA w <content> (L16) unieszkodliwia tymczasowo HTML-owe znaczniki, które mogły się w komentarzu pojawić (nowa linia, pogrubienie, itd.).

Czy parsujemy plik z feedem w celu dodania <entry> z nowym komciem? Nie utrudniajmy sobie życia. Plik z feedem kończy się na znaczniku </feed> – wystarczy więc zamienić </feed> na informacje o komentarzu, a potem domknąć plik nowym </feed> (L22). Musimy także pamiętać o uaktualnieniu czasu ostatniej zmiany w nagłówku paszki. Robimy to prostym wyrażeniem regularnym szukając miejsca, w którym <updated> pojawia się na początku linijki (L21). Takie znaczniki występują również we wszystkich <entry> – ale my modyfikujemy tylko ten pierwszy, nagłówkowy.

Na podobnej zasadzie nowelizujemy również paszkę z najnowszymi komentarzami (L24-34), ale tam przeliczamy wpierw ilość komciów, tzn. ilość znaczników <entry> (L28). Jeżeli jest ich więcej 10, to usuwamy ten pierwszy, czyli chronologicznie najstarszy, ponieważ nie chcemy nadmuchiwać feedu bez ograniczeń (L29).

Paszkujcie.

  1. Czy zwiększyłbym klikalność notki tytułując ją „Hiponimy feedu”? 

  2. Dictionary.com definiuje je w tym kontekście w następujący sposób: „11a) a website or application that publishes updates from social media or news-collection websites in reverse chronological order; 11b) an XML-based web document that is updated automatically at predetermined intervals and includes descriptive titles or short descriptions and links to recent pages on a website”. 

  3. Nie w pełni zrozumiały jest dla mnie sposób użycia global w PHP. Zamiast dostawiać globalną deklarację do zmiennych w momencie ich definicji – żeby wprowadzić je odgórnie do globalnego scope’u – global używa się dopiero wówczas, gdy potrzebujemy jakiejś jeszcze-nie-globalnej-ale-już-prawie zmiennej wewnątrz funkcji. 






Komentarze

Borys (2024-05-22 15:49:45)

Tak, widzę pewne błędy i wypaczenia w formatowaniu powyższej notki. Wszystko zostanie poprawione na dniach.

Seji (2024-05-22 19:36:53)

Działa!



C O M E C O N