Вывод суммы прописью
Специально по просьбе Wassi Wassinen достал из нафталина, отряхнул пыль и публикую свой класс вывода сумм прописью, который основан на вот этих методах.
В оригинальной версии копейки писались цифрами, а теперь — буквами. Ради этого пришлось переписать больше половины кода.
А вот и готовый сниппет:
Скопировать, вставить, сохранить и вызывать как фильтр вывода или сниппет:
Сам класс вполне универсален и не завязан на MODX.
После его объявления идёт логика работы сниппета, которую можно легко изменить для вывода количества комментариев, или чего-то еще.
В оригинальной версии копейки писались цифрами, а теперь — буквами. Ради этого пришлось переписать больше половины кода.
А вот и готовый сниппет:
<?php
if (!class_exists('num2text')) {
class num2text {
public $zero = 'ноль';
public $male = array(
'single' => array(1 => 'один','два','три','четыре','пять','шесть','семь','восемь','девять'),
'ten' => array(1 => 'десять','одиннадцать','двенадцать','тринадцать','четырнадцать' ,'пятнадцать','шестнадцать','семнадцать','восемнадцать','девятнадцать'),
'twenty' => array(2 => 'двадцать','тридцать','сорок','пятьдесят','шестьдесят','семьдесят' ,'восемьдесят','девяносто'),
'hundred' => array(1 => 'сто','двести','триста','четыреста','пятьсот','шестьсот', 'семьсот','восемьсот','девятьсот')
);
public $female = array(
'single' => array(1 => 'одна','две','три','четыре','пять','шесть','семь','восемь','девять'),
'ten' => array(1 => 'десять','одиннадцать','двенадцать','тринадцать','четырнадцать' ,'пятнадцать','шестнадцать','семнадцать','восемнадцать','девятнадцать'),
'twenty' => array(2 => 'двадцать','тридцать','сорок','пятьдесят','шестьдесят','семьдесят' ,'восемьдесят','девяносто'),
'hundred' => array(1 => 'сто','двести','триста','четыреста','пятьсот','шестьсот', 'семьсот','восемьсот','девятьсот')
);
public $units = array(
array('триллион', 'триллиона', 'триллионов', 'male'),
array('миллиард', 'милиарда', 'миллиардов', 'male'),
array('миллион', 'миллиона', 'миллионов', 'male'),
array('тысяча', 'тысячи', 'тысяч', 'female'),
);
public function morph($num, array $words) {
$num = abs(intval(str_replace(' ', '', $num)));
$n = $num % 100;
if ($num === 0 || ($n > 10 && $n < 20)) {
return $words[2];
}
else {
$n = $n % 10;
if ($n > 1 && $n < 5) {
return $words[1];
}
elseif ($n == 1) {
return $words[0];
}
else {
return $words[2];
}
}
}
public function transform($num, array $values) {
$array = array();
$triplet = 0;
$num = sprintf('%0'.((count($this->units) * 3) + 3).'.0f', str_replace(' ', '', $num));
// Split by 3 symbols
$tmp = str_split($num, 3);
foreach($tmp as $k => $v) {
list($i1, $i2, $i3) = array_map('intval', str_split($v, 1));
if (!$i1 && !$i2 && !$i3) {
$triplet ++;
continue;
}
if (isset($this->units[$triplet])) {
$gender = $this->units[$triplet][3];
$values = $this->$gender;
}
if (is_null($i3)) {$i3 = $i2; $i2 = $i1; $i1 = null;}
// 1xx-9xx
if (!is_null($i1)) {
$array[] = $values['hundred'][$i1];
}
// 20-99
if ($i2 > 1) {
$array[] = $values['twenty'][$i2].' '.$values['single'][$i3];
}
// 10-19 || 1-9
else {
$array[] = $i2 > 0
? $values['ten'][$i3 + 1]
: $values['single'][$i3];
}
// thousands, billions etc.
if (isset($this->units[$triplet])) {
$array[]= $this->morph($v, $this->units[$triplet]);
}
$triplet ++;
}
return implode(' ', $array);
}
function ucfirst($input) {
mb_internal_encoding('UTF-8');
$string = mb_strtolower(trim($input));
$output = mb_strtoupper(mb_substr($string, 0, 1));
$output .= mb_substr($string, 1, mb_strlen($string));
return $output;
}
}
}
$output = array();
$class = new num2text();
$num = str_replace(',', '.', $input);
list($integer, $decimal) = explode('.', $num);
if ($decimal > 99) {$decimal = 99;}
// Integer
$output[] = empty($integer)
? $class->zero
: $class->transform($integer, $class->male);
$words = array('рубль', 'рубля', 'рублей');
$output[] = $class->morph($integer, $words);
// Decimal
if ($decimal < 10) {
$output[] = $class->zero;
}
$output[] = $class->transform($decimal, $class->female);
$words = array('копейка', 'копейки', 'копеек');
$output[] = $class->morph($decimal, $words);
$output = $class->ucfirst(implode(' ',$output));
return $output;
Скопировать, вставить, сохранить и вызывать как фильтр вывода или сниппет:
[[+price:num2text]]
[[+old_price:num2text]]
[[!num2text?&input=`[[+order_cost]]`]]
Сам класс вполне универсален и не завязан на MODX.
После его объявления идёт логика работы сниппета, которую можно легко изменить для вывода количества комментариев, или чего-то еще.
Комментарии: 5
Немножко запоздал. Отправил. :) Еще раз спасибо, думаю всем будет полезно иметь такой функционал.
На здоровье!
$input = 5.50;
выдаёт:
Пять рублей ноль пять копеек
со всеми нулями происходит так же
выдаёт:
Пять рублей ноль пять копеек
со всеми нулями происходит так же
Обрени сумму в ковычки:
$input = "5.50";
точно, дело в кавычках.
Благодарю
Благодарю
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.