[ruAgo] Дорабатываем output filter ":ago" на склонения по-русски

есть у нас dateAgo который пишет сколько прошло времени с даты или полную дату
есть родной ago который считает сколько прошло времени с даты, но не имеет правильного перечисления (только 1 или много)

сделал так чтобы все было по правилам Русского языка

<?php

/**
 * @author Гончаров Степан
 * @see https://wwsite.ru 
 * @version 0.0.1a
 * @example {$dateago | ruAgo : ['type' => 'strtotime']}
*/

if (!function_exists('decl')) {
  function decl($amount, $variants, $number = true, $delimiter = '|') {
      $variants = explode($delimiter, $variants);
      if (count($variants) < 2) {
          $variants = array_fill(0, 3, $variants[0]);
      } elseif (count($variants) < 3) {
          $variants[2] = $variants[1];
      }
      $modulusOneHundred = $amount % 100;
      switch ($amount % 10) {
          case 1:
              $text = $modulusOneHundred === 11
                  ? $variants[2]
                  : $variants[0];
              break;
          case 2:
          case 3:
          case 4:
              $text = ($modulusOneHundred > 10) && ($modulusOneHundred < 20)
                  ? $variants[2]
                  : $variants[1];
              break;
          default:
              $text = $variants[2];
      }

      return $number
          ? $amount . ' ' . $text
          : $text;
  };
}
$input = $modx->getOption('input', $scriptProperties, null);
if ($input == null) {
  return false;
}
$type = $modx->getOption('type', $scriptProperties, 'strtotime'); // strtotime - 20.03.2016 || time - unix формат
$year = $modx->getOption('year', $scriptProperties, 'год|года|лет');
$month = $modx->getOption('month', $scriptProperties, 'месяц|месяца|месяцев');
$week = $modx->getOption('weeks', $scriptProperties, 'неделя|недели|недель');
$day = $modx->getOption('day', $scriptProperties, 'день|дня|дней');
$hour = $modx->getOption('hour', $scriptProperties, 'час|часа|часов');
$minut = $modx->getOption('minut', $scriptProperties, 'минута|минуты|минут');
$second = $modx->getOption('second', $scriptProperties, 'секунда|секунды|секунд');
$outputSeparator = $modx->getOption('outputSeparator', $scriptProperties, ' ');



$agoTS = [];
$uts['start'] = ($type == 'strtotime') ? strtotime($input) : intval($input);
$uts['end'] = time();

if ($uts['start'] !== -1 && $uts['end'] !== -1) {
    if ($uts['end'] >= $uts['start']) {
        $diff = $uts['end'] - $uts['start'];

        $years = intval((floor($diff / 31536000)));
        if ($years) {
            $diff = $diff % 31536000;
        }

        $months = intval((floor($diff / 2628000)));
        if ($months) {
            $diff = $diff % 2628000;
        }

        $weeks = intval((floor($diff / 604800)));
        if ($weeks) {
            $diff = $diff % 604800;
        }

        $days = intval((floor($diff / 86400)));
        if ($days) {
            $diff = $diff % 86400;
        }

        $hours = intval((floor($diff / 3600)));
        if ($hours) {
            $diff = $diff % 3600;
        }

        $minutes = intval((floor($diff / 60)));
        if ($minutes) {
            $diff = $diff % 60;
        }

        $diff = intval($diff);
        $agoTS = [
            'years' => $years,
            'months' => $months,
            'weeks' => $weeks,
            'days' => $days,
            'hours' => $hours,
            'minutes' => $minutes,
            'seconds' => $diff,
        ];
    }
}

$ago = [];
if (!empty($agoTS['years'])) {
    $ago[] = decl($agoTS['years'], $year);
}
if (!empty($agoTS['months'])) {
    $ago[] = decl($agoTS['months'], $month);
}
if (!empty($agoTS['weeks']) && empty($agoTS['years'])) {
    $ago[] = decl($agoTS['weeks'], $week);
}
if (!empty($agoTS['days']) && empty($agoTS['months']) && empty($agoTS['years'])) {
    $ago[] = decl($agoTS['days'], $day);
}
if (!empty($agoTS['hours']) && empty($agoTS['weeks']) && empty($agoTS['months']) && empty($agoTS['years'])) {
    $ago[] = decl($agoTS['hours'], $hour);
}
if (!empty($agoTS['minutes']) && empty($agoTS['days']) && empty($agoTS['weeks']) && empty($agoTS['months']) && empty($agoTS['years'])) {
    $ago[] = decl($agoTS['minutes'], $minut);
}
if (empty($ago)) { /* handle <1 min */
    $ago[] = decl($agoTS['seconds'], $second);
}
return implode($outputSeparator, $ago);
вызываем
{$dateago | ruAgo}
обратите внимание что умолчанию принимает время в формате для php метода strtotime()
если у вас unix формат времени то передайте параметр type в принципе любое значение)))
Stepan
30 июля 2024, 17:54
modx.pro
529
+3

Комментарии: 5

Николай Савин
30 июля 2024, 19:54
0
Не уловил, В чем отличие от dateAgo?
    Stepan
    01 августа 2024, 06:14
    0
    в dateAgo кажется через год выводит просто дату
    а мне нужно было чтобы всегда было количество прошедшее со старта
    Дима Касаткин
    31 июля 2024, 14:30
    +1
    Степан, спасибо что поделился!
    Проверь плиз заголовок, что-то с ним не так)
    Предлагаю допилить вот так: «[ruAgo] Дорабатываем output filter ":ago" на склонения по-русски»
      Ivan
      31 июля 2024, 20:58
      0
      Я подумал это шутка такая) Типа отсылка к тому что работало не корректно, а теперь правильно)
        Stepan
        01 августа 2024, 06:15
        +1
        Готово! Спасибо!
        оформление это не мое....
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        5