Czy w API zachować te same reguły routingu?

0

Przymierzamy się powoli do jakiegoś API dla 4programmers.net. W związku z tym pytanie, co myślicie: Czy URL w API powinny wyglądać tak samo jak URL w części webowej?

URL na 4programmers.net wyglądają jak wyglądają ze względów - powiedzmy - "historycznych". Tzn. pierwsza litera w segmencie jest pisana wielką litera. I tak mamy np. /Mikroblogi czy /Praca, czy /Login. Jak można zauważyć, część jest pisana w wersji PL a część w EN (ze względów SEO oczywiście). Dla ułatwienia możemy zrobić, że adres api.4programmers.net/Mikroblogi będzie zwracała listę wpisów w JSON. Możemy jednak porzucić tę konwencję w API i stosować linki w wersji EN (małymi literami), czyli: api.4programmers.net/microblogs.

Co o tym myślicie? Wydaje mi się ze ta druga opcja?

2

Obstawiałbym za jedną wersją, i najlepiej jednojęzyczną. Konwencja wielkich liter do mnie nie przemawia, i jestem za tym drugim rozwiązaniem.

0

Mnie osobiście wszystko jedno, która koncepcja, byle była "spójna wewnętrznie", jak pisze @Hispano-Suiza. Mogą być litery wielkie i małe, po polsku i po angielsku. Jednak jest jeszcze, jak ja to mógłbym nazwać, "spójność zewnętrzna": czy zależy nam na tym, żeby API forum podążało za jakimś trendem w budowaniu API (jeśli w tym są jakieś trendy)? Może większość API takich for jak to jest po angielsku małymi literami (nie sprawdzałem), i chcemy też tak mieć?

Jakby co, to ja się właśnie uczę OpenAPI. Fajne to, wydaje się takie przemyślane. :)

PS. @Adam Boduch, a są jakieś specjalne powody, dla których zabrałeś się za tworzenie API? Może one implikują użycie jakiejś konwencji.

0

Z jednej strony zawsze byłem za prostym, anglojęzycznym, małoliterowym™ (lowercase) stylem (spotykałem kwiatki typu getLudzie, brr), jednakże jeśli na stronie są Mikroblogi, a w API ma być microblogs, to w oczy kłuje spójność (a raczej jej brak).. szczególnie, że obok będzie Login i login, dlatego nie jestem jakoś święcie przekonany, że microblogs byłoby tu lepsze.

1

Aktualne API:

  • Zwraca HTML'a który ma ładnie wyglądać
  • Raczej nie będzie wykorzystywany przez klientów innych niż przeglądarka
  • Markup będzie się zmieniał żeby odpowiadać walorom estetyki, UI

Nowe API:

  • Zwraca (pewnie) JSON/XML , który ma być spójny
  • Będzie wykorzystywany przez różne toole, aplikacje, mody
  • Struktura będzie taka sama, żeby zachować kompatybilność w przód

Można zauważyć, że (poza tym że zwracają taki sam kontent w różnych formach) to te dwa API nie mają ze sobą nic wspólnego. Po co więc na siłę tworzyć spójne nazwy?

2
Silv napisał(a):

Ale dlaczego tworzenie spójnych nazw "na siłę"?

  1. Nie trudno wyobrazić sobie sytuację w której zajdzie potrzeba dodania takich zasobów/funkcji w nowym API, które nie mają żadnego odzwierciedlenia w aktualnym i odwrotnie (np. widok pisania postu (GET /Forum/Java/Submit) nie ma żadnego sensu w API "nie dla ludzi"). Wtedy wspólne nazwy staną się problematyczne.
  2. API po angielsku to wręcz prawo wszechświata. Wyobrażasz sobie że chcesz skorzystać z API, a tam zasoby po rosyjsku? /пользователь/14
3

Na github jest już pierwszy endpoint do API, zwracający listę mikroblogów. Pewnie trzeba będzie dodać jeszcze jakąś numeracje wersji - np. api.4programmers.net/v1/... na wszelki wypadek gdyby się coś kiedyś zmieniło :)

0
Adam Boduch napisał(a):

Na github jest już pierwszy endpoint do API, zwracający listę mikroblogów. Pewnie trzeba będzie dodać jeszcze jakąś numeracje wersji - np. api.4programmers.net/v1/... na wszelki wypadek gdyby się coś kiedyś zmieniło :)

Nie ma testów? :D

2

Chodzi mi o to, że gdybyśmy dodali/usunęli jakieś pola z JSON to wtedy stary format zostałby pod URL api.4programmers.net/v1/microblogs a nowy format pod URL api.4programmers.net/v2/microblogs.

Ale nie - nie ma jeszcze testów do API. Mam nadzieje, że może zachęcę społeczność do współtworzenia kodu i ktoś doda pull requesta :)

1
Adam Boduch napisał(a):

Ale nie - nie ma jeszcze testów do API. Mam nadzieje, że może zachęcę społeczność do współtworzenia kodu i ktoś doda pull requesta :)

Jako że nie mam kontrybutora, tylko wszystko PR'ami, to raczej nie chce mi sie.

Ale, jestem skłonny napisać bogatą dokumentację online do tego nowego api, która może być podobna do np dokumentacji T-Regx'a. @Adam Boduch jest sens?

0
Adam Boduch napisał(a):

Moja propozycja: https://api.4programmers.net/v1/microblogs

Bez parametrów zwraca wszystkie? Czy te ze strony głównej?

0
TomRiddle napisał(a):
Adam Boduch napisał(a):

Moja propozycja: https://api.4programmers.net/v1/microblogs

Bez parametrów zwraca wszystkie? Czy te ze strony głównej?

Wszystkie, ale dodane jest stronnicowanie. Zwróć uwagę, że na dole JSON-a masz ilość stron. Możesz przechodzić na kolejne podstrony.

0

Adam dlaczego zwracasz znaczniki html, czy to tylko chwilowo tak? ;)

0

Zwracam sparsowaną treść postów (markdown => html).

2

Kolejny endpoint zwracający listę wątków (póki co na serwerze testowym tylko): http://api.dev.4programmers.info/v1/topics

Zwraca tablice posts z dwoma postami - pierwszym oraz ostatnim (czyli tak jak w widoku listy wątków), pare informacji o samym wątku oraz kategorii forum. Dodam jeszcze sortowanie czy też filtrowanie po ID kategorii. Myślicie że jest ok? Coś jeszcze brakuje?

Myślałem, że kolejny endpoint /topics/123123 będzie wyświetlał całą zawartość wątku, wraz ze wszystkimi postami. Będzie ok? :)

{
  "data": [
    {
      "id": 25,
      "subject": "Hello World folks",
      "score": 0,
      "views": 709,
      "replies": 2,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Off-Topic/Dla_poczatkujacych/25-hello_world_folks",
      "forum": {
        "id": 3,
        "name": "Dla początkujących",
        "slug": "Off-Topic/Dla_poczatkujacych"
      },
      "posts": [
        {
          "id": 115,
          "created_at": "2019-01-26T17:52:21+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 117,
          "created_at": "2019-03-12T20:12:35+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": []
    },
    {
      "id": 24,
      "subject": "nowy watek na strone glowna juuuhu",
      "score": 0,
      "views": 1010,
      "replies": 5,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Oceny_i_recenzje/24-nowy_watek_na_strone_glowna_juuuhu",
      "forum": {
        "id": 6,
        "name": "Oceny i recenzje",
        "slug": "Oceny_i_recenzje"
      },
      "posts": [
        {
          "id": 114,
          "created_at": "2019-01-05T20:13:50+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 122,
          "created_at": "2019-08-26T14:57:20+02:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": []
    },
    {
      "id": 22,
      "subject": "HELLO",
      "score": 0,
      "views": 731,
      "replies": 2,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Newbie/22-hello",
      "forum": {
        "id": 1,
        "name": "Newbie",
        "slug": "Newbie"
      },
      "posts": [
        {
          "id": 104,
          "created_at": "2018-12-27T15:16:51+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 113,
          "created_at": "2019-01-05T20:06:57+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": [
        {
          "id": 23,
          "name": "test",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/test"
        }
      ]
    },
    {
      "id": 21,
      "subject": "hello world",
      "score": 0,
      "views": 400,
      "replies": 0,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Newbie/21-hello_world",
      "forum": {
        "id": 1,
        "name": "Newbie",
        "slug": "Newbie"
      },
      "posts": [
        {
          "id": 103,
          "created_at": "2018-12-27T15:16:33+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 103,
          "created_at": "2018-12-27T15:16:33+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": []
    },
    {
      "id": 20,
      "subject": "lorem ipsum",
      "score": 0,
      "views": 492,
      "replies": 0,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Newbie/20-lorem_ipsum",
      "forum": {
        "id": 1,
        "name": "Newbie",
        "slug": "Newbie"
      },
      "posts": [
        {
          "id": 101,
          "created_at": "2018-11-23T12:38:17+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 101,
          "created_at": "2018-11-23T12:38:17+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": []
    },
    {
      "id": 19,
      "subject": "Code review",
      "score": 0,
      "views": 0,
      "replies": 0,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Oceny_i_recenzje/19-code_review",
      "forum": {
        "id": 6,
        "name": "Oceny i recenzje",
        "slug": "Oceny_i_recenzje"
      },
      "posts": [
        {
          "id": 100,
          "created_at": "2018-11-22T10:16:58+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 100,
          "created_at": "2018-11-22T10:16:58+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": []
    },
    {
      "id": 15,
      "subject": "hello world",
      "score": 0,
      "views": 918,
      "replies": 1,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Newbie/15-hello_world",
      "forum": {
        "id": 1,
        "name": "Newbie",
        "slug": "Newbie"
      },
      "posts": [
        {
          "id": 50,
          "created_at": "2018-11-14T10:29:37+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 98,
          "created_at": "2018-11-21T12:20:34+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": []
    },
    {
      "id": 11,
      "subject": "test",
      "score": 0,
      "views": 672,
      "replies": 0,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Off-Topic/11-test",
      "forum": {
        "id": 5,
        "name": "Off-Topic",
        "slug": "Off-Topic"
      },
      "posts": [
        {
          "id": 22,
          "created_at": "2017-05-15T21:12:04+02:00",
          "user_name": "Nieposkromiony Mleczarz",
          "user": null
        },
        {
          "id": 22,
          "created_at": "2017-05-15T21:12:04+02:00",
          "user_name": "Nieposkromiony Mleczarz",
          "user": null
        }
      ],
      "tags": []
    },
    {
      "id": 9,
      "subject": "tabela",
      "score": 1,
      "views": 677,
      "replies": 0,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Python/9-tabela",
      "forum": {
        "id": 2,
        "name": "Python",
        "slug": "Python"
      },
      "posts": [
        {
          "id": 20,
          "created_at": "2017-03-18T17:04:04+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 20,
          "created_at": "2017-03-18T17:04:04+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": []
    },
    {
      "id": 8,
      "subject": "Dodanie zalacznika",
      "score": 0,
      "views": 752,
      "replies": 0,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Newbie/8-dodanie_zalacznika",
      "forum": {
        "id": 1,
        "name": "Newbie",
        "slug": "Newbie"
      },
      "posts": [
        {
          "id": 19,
          "created_at": "2017-03-16T08:23:12+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 19,
          "created_at": "2017-03-16T08:23:12+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": []
    },
    {
      "id": 7,
      "subject": "zagadka finger Firefox finger 4programmers.net finger Russia USSR",
      "score": 0,
      "views": 7717,
      "replies": 43,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Newbie/7-zagadka_finger_firefox_finger_4programmersnet_finger_russia_ussr",
      "forum": {
        "id": 1,
        "name": "Newbie",
        "slug": "Newbie"
      },
      "posts": [
        {
          "id": 16,
          "created_at": "2017-03-12T16:18:45+01:00",
          "user_name": "Wojciech Pijanowski",
          "user": null
        },
        {
          "id": 102,
          "created_at": "2018-12-27T15:16:15+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": [
        {
          "id": 5,
          "name": "c++",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/c%2B%2B"
        }
      ]
    },
    {
      "id": 6,
      "subject": "Sugestia",
      "score": 0,
      "views": 1601,
      "replies": 3,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Off-Topic/6-sugestia",
      "forum": {
        "id": 5,
        "name": "Off-Topic",
        "slug": "Off-Topic"
      },
      "posts": [
        {
          "id": 14,
          "created_at": "2017-03-12T15:17:06+01:00",
          "user_name": "@{Artur Protasewicz}",
          "user": null
        },
        {
          "id": 18,
          "created_at": "2017-03-12T17:12:54+01:00",
          "user_name": null,
          "user": {
            "id": 10,
            "name": "Artur Protasewicz",
            "photo": "https://dev.4programmers.info/uploads/photo/58/58b7d3033b911.jpg"
          }
        }
      ],
      "tags": [
        {
          "id": 4,
          "name": "c#",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/c%23"
        }
      ]
    },
    {
      "id": 5,
      "subject": "Test, Artur Protasewicz, wymiary obrazka profilowego na forum",
      "score": 0,
      "views": 1109,
      "replies": 1,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Off-Topic/5-test_artur_protasewicz_wymiary_obrazka_profilowego_na_forum",
      "forum": {
        "id": 5,
        "name": "Off-Topic",
        "slug": "Off-Topic"
      },
      "posts": [
        {
          "id": 12,
          "created_at": "2017-03-02T09:11:29+01:00",
          "user_name": null,
          "user": {
            "id": 10,
            "name": "Artur Protasewicz",
            "photo": "https://dev.4programmers.info/uploads/photo/58/58b7d3033b911.jpg"
          }
        },
        {
          "id": 13,
          "created_at": "2017-03-08T12:49:14+01:00",
          "user_name": null,
          "user": {
            "id": 10,
            "name": "Artur Protasewicz",
            "photo": "https://dev.4programmers.info/uploads/photo/58/58b7d3033b911.jpg"
          }
        }
      ],
      "tags": [
        {
          "id": 21,
          "name": "profil",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/profil"
        },
        {
          "id": 22,
          "name": "grafika",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/grafika"
        },
        {
          "id": 23,
          "name": "test",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/test"
        },
        {
          "id": 24,
          "name": "dev",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/dev"
        }
      ]
    },
    {
      "id": 4,
      "subject": "test dodawania wątków przez niezalogowanych",
      "score": 0,
      "views": 625,
      "replies": 0,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Off-Topic/4-test_dodawania_watkow_przez_niezalogowanych",
      "forum": {
        "id": 5,
        "name": "Off-Topic",
        "slug": "Off-Topic"
      },
      "posts": [
        {
          "id": 11,
          "created_at": "2017-02-22T19:32:37+01:00",
          "user_name": "Skromny Samiec",
          "user": null
        },
        {
          "id": 11,
          "created_at": "2017-02-22T19:32:37+01:00",
          "user_name": "Skromny Samiec",
          "user": null
        }
      ],
      "tags": []
    },
    {
      "id": 3,
      "subject": "REST API vs GraphQL. Co wybrać?",
      "score": 0,
      "views": 835,
      "replies": 0,
      "is_sticky": 0,
      "is_locked": 0,
      "locked_at": null,
      "url": "http://dev.4programmers.info/Forum/Newbie/3-rest_api_vs_graphql_co_wybrac",
      "forum": {
        "id": 1,
        "name": "Newbie",
        "slug": "Newbie"
      },
      "posts": [
        {
          "id": 9,
          "created_at": "2017-01-23T16:58:35+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        },
        {
          "id": 9,
          "created_at": "2017-01-23T16:58:35+01:00",
          "user_name": null,
          "user": {
            "id": 1,
            "name": "admin",
            "photo": "https://dev.4programmers.info/uploads/photo/5b/5bedd6f82260b.jpg"
          }
        }
      ],
      "tags": [
        {
          "id": 15,
          "name": "graphql",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/graphql"
        },
        {
          "id": 16,
          "name": "rest",
          "real_name": null,
          "logo": "",
          "url": "http://dev.4programmers.info/Praca/Technologia/rest"
        }
      ]
    }
  ],
  "links": {
    "first": "http://api.dev.4programmers.info/v1/topics?page=1",
    "last": "http://api.dev.4programmers.info/v1/topics?page=2",
    "prev": null,
    "next": "http://api.dev.4programmers.info/v1/topics?page=2"
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 2,
    "path": "http://api.dev.4programmers.info/v1/topics",
    "per_page": 15,
    "to": 15,
    "total": 17
  }
}
0

Tak głośno myślę... może nie potrzeba dodawać informacji o tych dwóch postach w endpoincie /topics a dopiero w endpoincie /topics/xxx gdzie podajemy ID wątku? Wówczas wyświetlamy wszystkie posty w danym wątku....

0

Tu może być wiele różnych rzeczy. Myślę że najrozsądniej byłoby ustalić to co ma być albo nie wyświetlane domyślnie (bez żadnych parametrów na wejściu) a reszta to po prostu kwestia odpowiednich parametrów wejściowych w żądaniu przez takiego CURL-a albo cokolwiek innego.

3

@Adam Boduch: Coś się rozsynchronizowały wersje Coyote pomiedzy dev i prod - API produkcyjne: https://api.4programmers.net/v1/posts/1646171 oraz API serwera DEV: http://api.dev.4programmers.info/v1/posts/123 zwracają kompletnie dwa różne obiekty.

Swoją drogą to jest breaking change, więc chyba powinno już być v2, ale że jestem jedynym użytkownikiem API to nie będę narzekał :P

2

Miło że ktoś korzysta z API :)

Tak, serwer dev jest do tyłu z aktualizacjami :) Wersja dev jeszcze siedzi na starym serwerze. Jak tylko przeniesiemy na nowy serwer, to myślę że aktualizacje będą obywać się na bieżąco. Na pewno do końca miesiąca problem zostanie rozwiązany.

Miej na uwadze że ten endpoint nie jest jeszcze udukumentowany chociaż mam nadzieje że już się nie zmieni :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1