Autor wpisu: Śpiechu, dodany: 16.03.2012 16:06, tagi: php
Pomysł na wpis dał mi kilka dni temu Facebook, a dokładniej ich totalnie niekonsekwentne oznaczenia co się kiedy wydarzyło na naszej tablicy. Raz jest to 23 minut(y) temu, raz 7 godz. temu, jeszcze inaczej około godziny temu. Być może różne ekipy robią osobno opisy czasu i stąd różnice. Postanowiłem dla sportu zmierzyć się z problemem. Powstało takie coś jak Timespan Smarty Modifier.
Opis jak to zainstalować, wymagania i sposób użycia możecie sobie przeczytać w moim kaleczonym angielskim w GitHubie. Tutaj chciałbym się skupić jak to działa. Najwygodniejszym sposobem korzystania z biblioteki jest poprzez modyfikator w szablonach Smarty, a więc {$jakaśZmienna|naszModyfikator}
.
Przede wszystkim sama nazwa pliku musi nazywać się modifier.nazwa.php, za to funkcja smarty_modifier_nazwa($argument). Pierwszy argument automatycznie dostaje wartość zmiennej, dla której wywołujemy modyfikator. Jeśli chcemy, następne podajemy po dwukropku. Drobna uwaga: nigdy niczego nie „echujemy”, tylko zwracamy poprzez return. Chodzi o łańcuchowe łączenie modyfikatorów.
Z uwagi na to, że całość rozrosła się do ponad 400 linii kodu, nie ma sensu wszystkiego tutaj przytaczać. Skupię się na najważniejszych rzeczach.
Całość ma formę klasy abstrakcyjnej rozszerzanej przez poszczególne języki. Na podstawie zadeklarowanego języka skrypt próbuje znaleźć sobie właściwą klasę (fragm. modifier.timespan.php):
$className = 'Spiechu\TimeSpan\TimeSpan' . strtoupper($lang); if (class_exists($className)) { $timeSpan = new $className(); // sprawdz czy klasa rozszerza AbstractTimeSpan if (!($timeSpan instanceof Spiechu\TimeSpan\AbstractTimeSpan)) { $timeSpan = new Spiechu\TimeSpan\TimeSpanEN(); } } else { // jesli nie ma takiego jezyka lub klasa niewlasciwa uzywam angielskiego $timeSpan = new Spiechu\TimeSpan\TimeSpanEN(); }
Potem tylko konfigurujemy klasę i zwracamy wynik:
$timeSpan->setStartDate($date)->showSuffix($suffix); return $timeSpan->getTimeSpan();
W klasie AbstractTimeSpan z kolei mamy trochę logiki związanej z obliczaniem interwału:
$curDate = new \DateTime('now'); $diff = $curDate->diff($this->_startDate); //otrzymujemt obiekt DateInterval
Począwszy od największej jednostki (rok) odpytujemy $diff która z jego zmiennych publicznych jest większa od 0 oraz za pomocą metod isHalfUnit($actualUnit, $fullUnit)
, almostFullUnit($actualUnit, $fullUnit)
sprawdzamy czy może przekroczyliśmy połowę obecnej jednostki, większej jednostki oraz czy nie można jej zaokrąglić do następnej całej.
Klasy rozszerzające implementują m.in. metodę getUnit($howMany, $unitSymbol, $half). Liczebniki angielskie są tak trudne, że potrzeba na nie aż 1 linijki:
if ($howMany > 1) $howMany = 2; return $this->_units[$howMany][$unitSymbol];
Jeśli mowa o $this->_units to wygląda to tak: