Вывод суммы прописью

 
Специально по просьбе Wassi Wassinen достал из нафталина, отряхнул пыль и публикую свой класс вывода сумм прописью, который основан на вот этих методах.

В оригинальной версии копейки писались цифрами, а теперь — буквами. Ради этого пришлось переписать больше половины кода.
 
А вот и готовый сниппет:
<?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'),);publicfunction 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];}}}publicfunction 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-9xxif(!is_null($i1)){
				$array[]= $values['hundred'][$i1];}// 20-99if($i2 >1){
				$array[]= $values['twenty'][$i2].' '.$values['single'][$i3];}// 10-19 || 1-9else{
				$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);// Decimalif($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.
После его объявления идёт логика работы сниппета, которую можно легко изменить для вывода количества комментариев, или чего-то еще.