Nie znalazłem artykułu, który temat omawiał by wystarczająco wyczerpująco i jednoznacznie. Ponieważ w trakcie prac nad jednym z dodatków napotkałem na konieczność dogłębnego zrozumienia, jak działa instalator Joomla!, więc postanowiłem spisać swoje wnioski. Może komuś się przydadzą.

 

 

Plik zwany po angielsku manifestem, z rozszerzeniem .xml:
  • podaje podstawowe informacje o rozszerzeniu, takie jak: nazwa, kategoria,
  • podaje podstawowe informacje o autorze (autorach) rozszerzenia,
  • informuje o sposobie instalacji i dezinstalacji dodatku.

Inne nazwy tego pliku to: deskryptor, plik instalacyjny, plik konfiguracyjny, plik .xml.

 

 

W artykule krótko omawiam składnię i sposób korzystania z pliku manifestu .xml w przypadku tworzenia rozszerzeń do środowiska Joomla! 1.5.x typu dodatek (ang. plugin).

 

 

 

Zapraszam do lektury!

 

Plik manifestu to mówiąc najprościej instrukcja, dzięki której wbudowany w środowisko J! instalator będzie wiedział gdzie umieścić informacje zgromadzone w paczce instalacyjnej.

 

 

Gdzie znajdziemy instalator? Znajdziemy go na zapleczu naszej witryny. Menu -> Rozszerzenia -> Instalator.

 

 

 

Paczki instalacyjne dodatków dla J! to pliki skompresowane do archiwum .zip. Przyjrzyjmy się takiej przykładowej paczce. Zachęcam do ściągnięcia przykładowej paczki jakiegoś dodatku, najlepiej takiego, którego działanie znamy i rozumiemy.

 

W nazwie często zakodowana jest wersja środowiska J! oraz wersja dodatku. Załóżmy na potrzeby tego artykułu, że zajmujemy się fikcyjnym dodatkiem o jakże sympatycznie brzmiącej nazwie 'ewulka'. Jak więc może wyglądać nazwa pliku dodatku? Na przykład tak:

 

 

 

ewulka_J1.5-2.11.zip

 

ewulka_2.11_PL.zip

 

ewulka-2.11_J1.5.zip

 

tymczasowy.zip

 

 

 

Nazwa nie ma więc większego znaczenia, ale ze względów porządkowych warto trzymać się jakiejś konwencji i systematycznie jej przestrzegać. Zalecam pierwszy z wymienionych przykładów.

 

 

 

Ponieważ .zip jest dosyć popularnym typem archiwum, więc możemy je rozpakować posługując się np. swoim ulubionym menedżerem plików i obejrzeć jego zawartość. Prawdopodobnie będzie ono wyglądało następująco:

 

 

paczka_J15_1.21.zip:

 

katalog

 

plik.xml

 

plik.php

 

 

 

Katalog jest nieobowiązkowy, czyli w przypadku małych dodatków może go po prostu nie być. Uwaga na nazwy. Jeżeli nasz dodatek nazwiemy 'ewulka', to taką samą nazwę powinien nosić katalog oraz wspomniane pliki:

 

 

ewulka_J1.5-2.11.zip:

 

ewulka

 

ewulka.xml

 

ewulka.php

 

 

 

Warto się trzymać tej konwencji, bo nazwy klas czy funkcji w kodzie dodatku bazują na nazwie pliku .php. Dla zainteresowanych, szczegóły zostały opisane tutaj. Z tego samego powodu kodowanie wersji dodatku w nazwie plików czy katalogu wewnątrz pliku jest złym pomysłem.

 

 

 

Co my tu mamy. W katalogu mogą być inne podkatalogi i często tak właśnie jest. Zdarza się, że obok głównego katalogu (ewulka) znajdziemy też katalog z wersjami językowymi dodatku o nazwie languages. Katalog ten zawiera pliki z rozszerzeniem .ini.

 

ewulka_J1.5-2.11.zip:

ewulka

languages

ewulka.xml

ewulka.php

 

 
 

Uwaga: złym pomysłem jest kodowanie wersji dodatku w nazwie katalogów lub plików wewnątrz paczki. Wersja jest przechowywana w tytułowym pliku manifestu (.xml).

 

 

 

Plik .php (ewulka.php) zawiera kod, skrypt dodatku. Działanie dodatku jest zdefiniowane właśnie w tym pliku.

Plik .xml (ewulka.xml) zawiera manifest dodatku, czyli instrukcję dla instalatora i deinstalatora.

 

 

 

Zajmijmy się teraz w szczegółach plikiem manifestu .xml. Jego zawartość jest napisana w języku znaczników .xml. Mówiąc najprościej kolejne parametry pliku są umieszczone pomiędzy znacznikami: <otwierającym> i </zamykającym>. Dopuszczalne jest zagnieżdżanie znaczników. Szczególna para znaczników, o której warto pamiętać, to:

<!-- ... -->

Wszystko co, znajdzie się pomiędzy tymi znacznikami (np. powyższe trzy kropki) zostanie potraktowane jako komentarz.

 

Zaczynamy. Tworzymy przykładowy plik 'ewulka.xml' i przekopiowujemy do niego następującą zawartość:

 

<?xml version="1.0" encoding="utf-8"?>
<!-- upgrade = shall be able to overwrite existing files -->
<install version="1.5" type="plugin" group="content" method="upgrade">
    <name>ewulka</name>
    <!-- The following elements are optional and free of formatting conttraints -->   
    <creationDate>2010-04-05</creationDate>
    <author>mslonik</author>
    <authorEmail>Ten adres pocztowy jest chroniony przed spamowaniem. Aby go zobaczyć, konieczne jest włączenie w przeglądarce obsługi JavaScript.</authorEmail>
    <authorUrl>http://mslonik.pl</authorUrl>
    <copyright>http://mslonik.pl</copyright>
    <license>GNU wer. 3</license>
    <!--  The version string is recorded in the components table -->
    <version>1.0</version>
    <!-- The description is optional and defaults to the name -->
    <description>SLIMBOXDESCINPLUGIN</description>
    <!-- Site Main File Copy Section -->
    <!-- Note the folder attribute: This attribute describes the folder
         to copy FROM in the package to install therefore files copied
         in this section are copied from /site/ in the package -->
    <files>
        <filename plugin="ewulka">ewulka.php</filename>
        <folder>pierwszy</folder>
    </files>

    <languages folder="languages">
        <language tag="pl-PL">pl-PL.plg_content_ewulka.ini</language>
    </languages>

    <params>
    </params>
</install>

 

Znaczniki: Opis:
<!-- ... --> Komentarz
<?xml version="1.0" encoding="utf-8"?> Pierwszą linijkę zostawmy w spokoju. Póki co przyjmijmy, że tak musi być. Podajemy wersję języka 'xml' oraz kodowanie (encoding). Dla J1.5.x musi to być "utf-8".

<install version="1.5" type="plugin" group="content" method="upgrade">

(...)

</install>

 

Pomiędzy znacznikami 'install' mieści się szereg innych znaczników. Znacznik 'install' przyjmuje szereg parametrów:

  • type
  • group
  • method

 

Parametr 'type' może przyjąć następujące wartości:

  • plugin
  • module
  • component

Jeżeli type="plugin", to parametr 'group' może przyjąć następujące wartości:

  • authentication
  • content
  • editors
  • editors-xtd
  • search
  • system
  • user
  • xmlprc

Uwaga! Konieczne jest podanie wartości dla parametru 'group'. Wartości parametru 'group' odpowiadają rodzajom dodatków dopuszczalnych w środowisku J! 1.5.x.

 

Parametr 'method' może przyjąć następujące wartości:

  • upgrade <- próba instalacji już zainstalowanego dodatku  nie spowoduje wyświetlenia komunikatu ostrzegającego o próbie nadgrania istniejących plików; istniejące katalogi i pliki zostaną nadgrane zawartością paczki instalacyjnej.
  • jeżeli nie chcemy, by nowa wersja nadgrywała wersję poprzednią, wystarczy pominąć parametr 'method'.
<name>ewulka</name>

name -> nazwa dodatku

 

Informacja wpisana pomiędzy tymi znacznikami zostanie wyświetlona w polach tabeli, którą znajdziemy po zalogowaniu się na zaplecze J! i wybraniu z menu 'Rozszerzenia' -> 'Dodatki'.

Nieobowiązkowa grupa znaczników identyfikujących:

    <creationDate>2010-04-05</creationDate>
    <author>mslonik</author>
    <authorEmail>Ten adres pocztowy jest chroniony przed spamowaniem. Aby go zobaczyć, konieczne jest włączenie w przeglądarce obsługi JavaScript.</authorEmail>
    <authorUrl>http://mslonik.pl</authorUrl>
    <copyright>http://mslonik.pl</copyright>
    <license>GNU wer. 3</license>
    <version>1.0</version>
    <!-- Po opis sięgnie do pliku .ini, do sekcji zaczynającej się od słowa SLIMBOXDESCINPLUGIN -->
    <description>SLIMBOXDESCINPLUGIN</description>

Informacje wpisane za poniższymi znacznikami zostaną wyświetlone w polach tabeli, którą znajdziemy po zalogowaniu się na zaplecze J! i wybraniu z menu: 'Rozszerzenia' -> 'Instalator', a następnie zakładki 'Dodatki':

  • name,
  • version,
  • creationDate,
  • author.

 

Znaczniki:

  • creationDate -> data rozszerzenia;
  • author -> autor rozszerzenia;
  • authorEmail -> e-mail do autora (ów) rozszerzenia;
  • authorUrl -> strona www autora (ów);
  • copyright -> komu przysługuje prawo do rozszerzenia;
  • license -> licencja rozszerzenia;
  • wersja -> nr wersji rozszerzenia
  • description -> krótki opis rozszerzenia

są nieobowiązkowe, czyli mogą nie wystąpić. Ich wypełnienie znacznie jednak ułatwia odczyt podstawowych informacji.

 

Po znaczniku 'description' możemy zastosować sporo popularnych tagów języka HTML. Informacje tutaj wpisane zostaną wyświetlone po wybraniu przez użytkownika z menu 'Rozszerzenia' -> 'Dodatki', a następnie nazwy dodatku 'ewulka'. Warto tu umieścić swego rodzaju krótką instrukcję obsługi naszego rozszerzenia.

 

Innym sposobem dołączenia opisu jest wpisanie pomiędzy znacznikami 'description' jakiegoś słowa, np. SLIMBOXDESCINPLUGIN. Jest to informacja dla instalatora, że ma poszukać opisu w pliku językowym .ini. W tym pliku umieszczamy opis tuż za wybranym słowem:

 

SLIMBOXDESCINPLUGIN=(...)

<files>

...

</files>

Bardzo ważna, obowiązkowa grupa znaczników. To stąd instalator pobiera informacje gdzie przekopiować pliki z paczki instalacyjnej oraz jak je później usunąć. Szczegóły zostały opisane w tekście poniżej.

<languages>

<language> ... </language>

...

</languages>

Po tagu 'languages' może (ale nie musi) wystąpić następujący parametr:

  • folder="languages"

Parametr 'folder' wskazuje instalatorowi na nazwę katalogu, w którym są umieszczone pliki językowe.

 

Pliki językowe pozwalają na tzw. lokalizację rozszerzenia, czyli zawierają tłumaczenie na dany język wybranych elementów rozszerzenia. Kod rozszerzenia zawiera nazwy parametrów, w miejsca których podstawiane są łańcuchy tekstowe w danym języku. W zapleczu witryny ustawiamy język, w jakim ma być wyświetlana treść strony. Ta informacja jest przechowywana przez środowisko J! i wykorzystywana m.in. do wyświetlania informacji o rozszerzeniu w tym języku.

 

Pomiędzy tagami 'languages' mogą wystąpić tagi 'language'.

<language tag="pl-PL">pl-PL.plg_content_ewulka.ini</language>

Tagi 'language' służą do przekazania instalatorowi informacji o tym, na jakie języki zostało przetłumaczone dane rozszerzenie. Dla każdego języka przypada osobny plik językowy. Pliki językowe mają rozszerzenie .ini.

 

Po tagu 'language' musi wystąpić parametr:

  • tag="pl-PL"

Wartość parametru określa ustalony dla danego języka kod. Przykładowo dla języka polskiego jest to "pl-PL".

 

Dla plików językowych warto zachować konwencję nazw:

KodJezyka.RodzajRozszerzenia_TypRozszerzenia_NazwaRozszerzenia.ini

 

czyli przykładowo:

pl-PL.plg_content_ewulka.ini

<params>

<param ... />

...

</params>

Tagi 'params' służą do określenia parametrów, określających sposób działania rozszerzenia. Dostęp do tych parametrów w przypadku dodatków jest możliwy najczęściej poprzez zaplecze J!, menu 'Rozszerzenia' -> ' Dodatki' i wybranie nazwy dodatku. Poszczególne parametry są zdefiniowane w liniach zaczynających się od tagu 'param'.
<param name="nazwa parametru" type="typ parametru" default="ustawienie domyślne" label="etykieta"  description="opis parametru"/>

Po słowie 'param' mogą wystąpić parametry służące do określenia danego parametru:

  • name - nazwa parametru
  • type - typ parametru; podstawowe typy parametrów zostały przedstawione tutaj
  • default - wartość domyślna parametru
  • label - etykieta parametru
  • description - opis parametru, który zostanie wyświetlony po najechaniu kursorem myszy na nazwę parametru; zostanie wtedy wyświetlony "w chmurce"

 

Skąd instalator wie, które pliki zainstalować? Skąd instalator wie, które pliki usunąć? Gdzie instalator kopiuje pliki?

 

Na powyższe pytania niestety nie ma prostej odpowiedzi. Brakuje bowiem czytelnego mechanizmu, który pozwoliłby poinformować instalator co gdzie przenieść. Zadanie na pewnym poziomie ogólności wydaje się dosyć proste:

  • Na etapie instalacji chcemy przenieść plik (lub katalog) z paczki do struktury plików i katalogów środowiska J!
  • Na etapie usuwania chcemy usunąć tylko te pliki, które pierwotnie zostały przekopiowane do struktury plików i katalogów środowiska J!.

Nie możemy stworzyć w miejscu przeznaczenia odpowiadającej nam struktury katalogów, a następnie przekopiować do nich pliki. Chcąc uzyskać pewną strukturę katalogów i plików musimy ją najpierw stworzyć w paczce instalacyjnej.

 

Czas już odpowiedzieć na pytanie dokąd zostaną przeniesione nasze pliki i foldery. Ponieważ po znaczniku <install> podaliśmy parametr type="plugin", więc pliki i foldery znajdą się w katalogu:

(...)/plugins

Dalej doprezyzowując, jeżeli po znaczniku <install> podaliśmy parametr group="nazwa_gurpy", to znajdą się one w katalogu:

(...)/plugins/nazwa_grupy

 

Zarówno informacje o źródle, jak i przeznaczeniu oraz liście plików do usunięcia są przechowywane w pliku .xml pomiędzy znacznikami

<files>

...

</files>

W tym samym pliku .xml może być tylko jedna taka sekcja.

 

Co tam możemy znaleźć? Dwa rodzaje znaczników:

<filename> ... </filename>

oraz

<folder> ...</folder>

 

Pierwszy typ znacznika (filename) pozwala nam selektywnie przekopiować pliki z paczki w miejsce przeznaczenia. Tylko pliki, które zostaną przez nas wprost podane zostaną przekopiowane do miejsca przeznaczenia. Musimy jednak podać pełną ścieżkę dostępu do danego pliku. Instalator utworzy dokładnie takie same katalogi i umieści w nich wskazany przez nas plik.

 

Szczególną rolę odgrywa następująca, obowiązkowa formuła:

<filename plugin="ewulka">ewulka.php</filename>

Parametr plugin wskazuje na nazwę dodatku (plugin="ewulka"). Po wystąpieniu tego parametru, pomiędzy tagami 'filename' musi wystąpić nazwa głównego pliku realizującego funkcje dodatku (ewulka.php).

 

Co się stanie podczas usuwania dodatku? Cóż, instalator nie potrafi usuwać katalogów. Usunie tylko pliki wskazane pomiędzy znacznikami 'filename'.

 

Przykład: instalacja dodatku.

W paczce ewulka.zip tworzymy następujące drzewo katalogów wraz z plikami:

ewulka.zip/pierwszy/drugi/trzeci/pasztet.txt

ewulka.zip/pierwszy/drugi/trzeci/foka.txt

 

W manifeście dopisujemy sekcję 'filename':

<filename>pierwszy/drugi/trzeci/pasztet.txt</filename>

 

W efekcie instalator stworzy wszystkie katalogi potrzebne, by ścieżka dostępu wyglądała następująco:

(...)/plugins/content/pierwszy/drugi/trzeci

Pliki 'pasztet.txt' oraz 'foka.txt' nie zostaną zainstalowane.

 

 

Przykład: usuwanie dodatku.

W manifeście podaliśmy następującą ścieżkę:

<filename>pierwszy/drugi/trzeci/pasztet.txt</filename>

W trakcie usuwania dodatku usunięty zostanie tylko plik

(...)/plugins/content/pierwszy/drugi/trzeci/pasztet.txt,

a nie zostaną usunięte katalogi 'pierwszy', 'drugi' oraz 'trzeci'.

 

 

Drugi typ znacznika (folder) pozwala na przeniesienie od razu całego katalogu wraz z całą zawartością. Zamiast więc pracowicie nazywać poszczególne pliki, od razu skopiuje wszystkie. Nie będziemy więc mieć kontroli nad każdym pojedynczym plikiem, ale będziemy mieć kontrolę nad całymi katalogami.

 

Przykład: instalacja dodatku.

W paczce ewulka.zip tworzymy następujące drzewo katalogów wraz z plikami:

ewulka.zip/pierwszy/drugi/trzeci/pasztet.txt

ewulka.zip/pierwszy/drugi/trzeci/czwarty/foka.txt

ewulka.zip/kolejny/podkatalog/pustak.txt

 

W manifeście dopisujemy sekcję 'files':

<files>pierwszy</files>

 

W efekcie instalator utworzy katalogi i przekopiuje pliki:

(...)/plugins/content/pierwszy/drugi/trzeci/pasztet.txt

(...)/plugins/content/pierwszy/drugi/trzeci/czwarty/foka.txt

 

Przykład: usuwanie dodatku.

W manifeście podaliśmy następującą ścieżkę:

<files>pierwszy</files>

W trakcie usuwania dodatku usunięty zostanie katalog '(...)/plugins/content/pierwszy' oraz wszystkie podkatalogi i pliki.

 

Polecam drugi sposób. Jest moim zdaniem wygodniejszy.

 

Niestety od tej reguły jest wyjątek. Nieco inaczej instalator traktuje tzw. pliki językowe, czyli pliki zawierające tłumaczenie rozszerzenia na dany język. Pliki te mają rozszerzenia .ini. Informacje o tym, gdzie te pliki się znajdują w paczce instalacyjnej są przekazywane pomiędzy tagami 'languages' poprzez parametr "folder". Parametr "folder" informuje program instalacyjny, gdzie w paczce instalacyjnej znajdują się pliki językowe. Położenie plików językowych, czyli miejsce, w które zostaną one przeniesione z paczki instalacyjnej, jest ustalone:

(...)/administrator/language

W tym katalogu znajdują się podkatalogi o nazwach identycznych jak przekazane w parametrze 'tag' tagu 'language'. To do nich przenoszone są pliki językowe.

 

Podsumowując:

Paczka 'paczka.zip' Kierunek Środowisko J!
skąd       -> dokąd
źródło       -> przeznaczenie

które katalogi i pliki?

te, które zostały podane w pliku manifest.xls, sekcja 'files'

     ->

 

(...)/plugins/

pliki językowe,

te, które zostały podane w pliku manifest.xls, sekcja 'languages'

     -> (...)/administrator/language

 

Ważną z punktu widzenia dbałości o bezpieczeństwo jest umieszczanie we wszystkich folderach, które umieszczamy w zasobach J! pliku 'index.html' o następującej zawartości:

<html><body bgcolor="#FFFFFF"></body></html>

 

Dlaczego należy to zrobić? Plik  'index.html' nie pozwala na wyświetlenie zawartości katalogu podczas prób nieautoryzowanego przeglądania zawartości katalogów umieszczonych w zasobach serwera www. Gdyby nie było pliku 'index.html', to niektóre z serwerów wyświetliłyby zawartość katalogu, czego zazwyczaj sobie nie życzymy.

 

Lektura uzupełniająca:

  1. http://docs.joomla.org/How_to_create_a_content_plugin
  2. http://developer.joomla.org/tutorials/184-how-to-create-a-joomla-plugin.html
  3. http://docs.joomla.org/Category:Plugins
  4. http://docs.joomla.org/Components:xml_installfile

Po polsku:

  1. http://wiki.joomla.pl/index.php/Plik_templateDetails.xml/Do_czego_s%C5%82u%C5%BCy_plik_templateDetails.xml%3F
  2. http://wiki.joomla.pl/index.php/Plik_templateDetails.xml/Manifest_XML_-_zestawienie_znacznik%C3%B3w

<filename>

...

</filename>

 

Komentowanie za pomocą rozszerzenia JComments zostało wyłączone. Zapraszam do dodawania komentarzy za pomocą aplikacji Disqus.