Source of file DatetimeExtension.php

Size: 9,452 Bytes - Last Modified: 2023-11-16T22:56:02+01:00

/home/websites/teicee/packagist/site/phpdoc/conf/../vendor/teicee/twig-bundle/src/Extension/DatetimeExtension.php

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
<?php
namespace TIC\TwigBundle\Extension;

use TIC\TwigBundle\Base\TICTwigExtension as BaseExtension;
use TIC\CoreBundle\Util\ConvertHelper;
#use TIC\CoreBundle\Util\StringHelper;

use Twig\TwigFilter;
use Twig\Environment;

/**
 * Filtres et fonctions twig de formattage de dates.
 * https://twig.symfony.com/doc/3.x/filters/format_datetime.html
 */
class DatetimeExtension extends BaseExtension
{

	public function getFilters(): array
	{
		return [
			new TwigFilter('fdate',     [$this, 'fdateFilter']                                      ),
			new TwigFilter('ftime',     [$this, 'ftimeFilter']                                      ),
			new TwigFilter('fdatetime', [$this, 'fdatetimeFilter']                                  ),
			new TwigFilter('ndatetime', [$this, 'ndatetimeFilter']                                  ),
			new TwigFilter('ldatetime', [$this, 'ldatetimeFilter'],     ['needs_environment'=>true] ),
			new TwigFilter('ldate',     [$this, 'ldateFilter'],         ['needs_environment'=>true] ),
			new TwigFilter('ltime',     [$this, 'ltimeFilter'],         ['needs_environment'=>true] ),
			new TwigFilter('ldatehour', [$this, 'ldatehourFilter'],     ['needs_environment'=>true] ),
			new TwigFilter('lhour',     [$this, 'lhourFilter'],         ['needs_environment'=>true] ),
			new TwigFilter('lmonth',    [$this, 'lmonthFilter'],        ['needs_environment'=>true] ),
			new TwigFilter('duration',  [$this, 'durationFilter'],      ['is_safe' => ['html']]     ),
		];
	}


	/**
	 * Formattage d'une date (ou chaine par défaut si date vide).
	 *
	 * @param  mixed    $value      Variable indiquant la date (objet DateTime sinon timestamp numérique)
	 * @param  string   $format     Motif avec la syntaxe de strftime() sinon date()
	 * @param  string   $default    Chaine à retourner par défaut si la variable est vide
	 * @return string               Chaine représentant la date avec le format indiqué
	 */
	public function fdateFilter($value, string $format = '%A %e %B %Y', string $default = ''): string
	{
		$date = ConvertHelper::timestamp($value);
		if ($date === null) return $default;
		
		if (\strpos($format, '%') === false) return \date($format, $date);
		
		$locale = \setlocale(LC_ALL, '0');
		\setlocale(LC_ALL, 'fr_FR.UTF8', 'fr_FR', 'fr', 'french');
		if (PHP_OS != 'Linux') $format = \str_replace('%e', '%#d', $format);
		$date = \strftime($format, $date);
		\setlocale(LC_ALL, $locale);
		return $date;
	}

	/**
	 * Formattage d'une date (ou chaine par défaut si date vide).
	 * Note: variante du filtre "fdate" avec un format par défaut incluant les heures
	 *
	 * @param  mixed    $value      Variable indiquant la date (objet DateTime sinon timestamp numérique)
	 * @param  string   $format     Motif avec la syntaxe de strftime() sinon date()
	 * @param  string   $default    Chaine à retourner par défaut si la variable est vide
	 * @return string               Chaine représentant la date avec le format indiqué
	 */
	public function fdatetimeFilter($value, string $format = '%A %e %B %Y - %H:%M', string $default = ''): string
	{
		return $this->fdateFilter($value, $format, $default);
	}

	/**
	 * Formattage d'un horaire (ou chaine par défaut si date vide).
	 *
	 * @param  mixed    $value      Variable indiquant la date (objet DateTime sinon timestamp numérique)
	 * @param  string   $format     Motif avec la syntaxe de strftime() sinon date()
	 * @param  string   $default    Chaine à retourner par défaut si la variable est vide
	 * @return string               Chaine représentant l'horaire avec le format indiqué
	 *
	 */
	public function ftimeFilter($value, string $format = 'H:i', string $default = ''): string
	{
		$date = ConvertHelper::timestamp($value);
		if ($date === null) return $default;
		
		return (\strpos($format, '%') === false) ? \date($format, $date) : \strftime($format, $date);
	}

	/**
	 * Formattage d'une date au format numérique 'YYYYMMDDhhmmss' (ou chaine par défaut si date vide).
	 *
	 * @param  mixed    $value      Variable indiquant la date (objet DateTime sinon timestamp numérique)
	 * @param  string   $default    Chaine à retourner par défaut si la variable est vide
	 * @return string               Chaine représentant la date sous sa forme numérique
	 */
	public function ndatetimeFilter($value, string $default = ''): string
	{
		$date = ConvertHelper::timestamp($value);
		if ($date === null) return $default;
		
		return \date('YmdHis', $date);
	}

	/**
	 * Formattage localisé d'une date avec horaire (selon des profils de formats).
	 */
	public function ldatetimeFilter(Environment $env, $date, ?string $dateFormat = 'medium', ?string $timeFormat = null, string $default = '', string $locale = null, $timezone = null, string $pattern = ''): string
	{
		// retourner NULL (ou autre valeur par défaut spécifiée) en l'absence de date
		if (($date === null) || ($date === '')) return $default;
		
		// timeFormat par défaut identique au dateFormat
		if ($timeFormat === null) $timeFormat = $dateFormat;
		
		// code original de Twig_Extensions_Extension_Intl::twig_localized_date_filter :
		$filter = $env->getFilter('format_datetime')->getCallable();
		return \call_user_func($filter, $env, $date, $dateFormat, $timeFormat, $pattern, $timezone, 'gregorian', $locale);
	}

	/**
	 * Formattage localisé d'une date sans horaire (selon des profils de formats).
	 */
	public function ldateFilter(Environment $env, $date, ?string $dateFormat = 'medium', string $default = '', string $locale = null, $timezone = null): string
	{
		return $this->ldatetimeFilter($env, $date, $dateFormat, 'none', $default, $locale, $timezone);
	}

	/**
	 * Formattage localisé d'un horaire (selon des profils de formats).
	 */
	public function ltimeFilter(Environment $env, $date, ?string $timeFormat = 'medium', string $default = '', string $locale = null, $timezone = null): string
	{
		return $this->ldatetimeFilter($env, $date, 'none', $timeFormat, $default, $locale, $timezone);
	}

	/**
	 * Formattage localisé d'une date avec horaire, mais sans les secondes (selon des profils de formats).
	 */
	public function ldatehourFilter(Environment $env, $date, ?string $dateFormat = 'medium', ?string $timeFormat = null, string $default = '', string $locale = null, $timezone = null): string
	{
		return \preg_replace('/(\d\d?:\d\d?):\d\d?/', '$1', $this->ldatetimeFilter($env, $date, $dateFormat, $timeFormat, $default, $locale, $timezone));
	}

	/**
	 * Formattage localisé d'un horaire, mais sans les secondes (selon des profils de formats).
	 */
	public function lhourFilter(Environment $env, $date, ?string $timeFormat = 'short', string $default = '', string $locale = null, $timezone = null): string
	{
		return \preg_replace('/(\d\d?:\d\d?):\d\d?/', '$1', $this->ldatetimeFilter($env, $date, 'none', $timeFormat, $default, $locale, $timezone));
	}

	/**
	 * Formattage localisé d'un mois (selon des profils de formats).
	 */
	public function lmonthFilter(Environment $env, $date, ?string $format = 'long', string $default = '', string $locale = null, $timezone = null): string
	{
		switch ($format) {
			case 'short' : $pattern = 'L'; break;
			case 'medium': $pattern = 'LL'; break;
			case 'long'  : $pattern = 'LLL'; break;
			case 'full'  : $pattern = 'LLLL'; break;
			default      : $pattern = 'LLL';
		}
		return $this->ldatetimeFilter($env, $date, 'none', 'none', $default, $locale, $timezone, $pattern);
	}

	/**
	 * Formattage d'une durée en décomposant un nombre de secondes avec toutes les unités intermédiaires appropriées.
	 *
	 * @param  mixed    $seconds    Durée à afficher en nombre de secondes
	 * @param  string   $sep        Séparateur pour la construction de la chaine de caractère
	 * @param  array    $units      Liste des unités utilisables pour la décomposition (parmis: C,D,Y,M,W,d,h,m,s)
	 * @param  string   $pluriel    Caractère à ajouter aux unités pour leurs formes plurielles
	 * @param  bool     $opt_week   Unité 'week' supprimée automatiquement si durée supérieure au mois (quelque soit la liste $units)
	 * @return string               Chaine de caractères décrivant la durée (ex: 123456789 => "46 mois 28 jours 19 heures 16 minutes")
	 */
	public function durationFilter($seconds, string $sep=' ', array $units=array('M'=>' mois','d'=>' jour','h'=>' heure','m'=>' minute'), string $pluriel='s', bool $opt_week=true): string
	{
		if ($seconds === null) return '';
		$seconds = \is_object($seconds) ? $seconds->getTimestamp() + $seconds->getOffset() : \intval($seconds);
		$sign = ($seconds < 0) ? '- ' : '';
		$seconds = \abs($seconds);
		
		$periods = array(
			'C' => 3155692600,
			'D' => 315569260,
			'Y' => 31556926,
			'M' => 2629743,
			'W' => 604800,
			'd' => 86400,
			'h' => 3600,
			'm' => 60,
			's' => 1,
		);
		// on supprime le découpage par semaines si on dépasse le mois
		if (($opt_week) && ($seconds >= $periods['M'])) unset($periods['W']);
		
		$durations = array();
		$range = \array_keys($units);
		foreach ($periods as $p=>$d) {
			if (! \in_array($p, $range)) continue;
			if ($seconds >= $d) {
				$durations[$p] = \floor($seconds / $d);
				$seconds -= $durations[$p] * $d;
			}
		}
		
		$list = array();
		foreach ($durations as $p=>$n) \array_push($list, $n . $units[$p] . ((($n>1)&&(\substr($units[$p],-1)!=$pluriel))?$pluriel:''));
		if (\count($list) == 0) \array_push($list, 0 . \array_pop($units));
		
		return $sign . \implode($sep, $list);
	}

}