I18N_Arabic
[ class tree: I18N_Arabic ] [ index: I18N_Arabic ] [ all elements ]

Source for file Numbers.php

Documentation is available at Numbers.php

  1. <?php
  2. /**
  3.  * ----------------------------------------------------------------------
  4.  *  
  5.  * Copyright (c) 2006-2012 Khaled Al-Sham'aa.
  6.  *  
  7.  * http://www.ar-php.org
  8.  *  
  9.  * PHP Version 5
  10.  *  
  11.  * ----------------------------------------------------------------------
  12.  *  
  13.  * LICENSE
  14.  *
  15.  * This program is open source product; you can redistribute it and/or
  16.  * modify it under the terms of the GNU Lesser General Public License (LGPL)
  17.  * as published by the Free Software Foundation; either version 3
  18.  * of the License, or (at your option) any later version.
  19.  *  
  20.  * This program is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU Lesser General Public License for more details.
  24.  *  
  25.  * You should have received a copy of the GNU Lesser General Public License
  26.  * along with this program.  If not, see <http://www.gnu.org/licenses/lgpl.txt>.
  27.  *  
  28.  * ----------------------------------------------------------------------
  29.  *  
  30.  * Class Name: Spell numbers in the Arabic idiom
  31.  *  
  32.  * Filename:   Numbers.php
  33.  *  
  34.  * Original    Author(s): Khaled Al-Sham'aa <khaled@ar-php.org>
  35.  *  
  36.  * Purpose:    Spell numbers in the Arabic idiom
  37.  *  
  38.  * ----------------------------------------------------------------------
  39.  *  
  40.  * Spell numbers in the Arabic idiom
  41.  *
  42.  * PHP class to spell numbers in the Arabic idiom. This function is very
  43.  * useful for financial applications in Arabic for example.
  44.  *    
  45.  * If you ever have to create an Arabic PHP application built around invoicing or
  46.  * accounting, you might find this class useful. Its sole reason for existence is
  47.  * to help you translate integers into their spoken-word equivalents in Arabic
  48.  * language.
  49.  * 
  50.  * How is this useful? Well, consider the typical invoice: In addition to a
  51.  * description of the work done, the date, and the hourly or project cost, it always
  52.  * includes a total cost at the end, the amount that the customer is expected
  53.  * to pay.
  54.  *   
  55.  * To avoid any misinterpretation of the total amount, many organizations (mine
  56.  * included) put the amount in both words and figures; for example, $1,200 becomes
  57.  * "one thousand and two hundred dollars." You probably do the same thing every time
  58.  * you write a check.
  59.  * 
  60.  * Now take this scenario to a Web-based invoicing system. The actual data used to
  61.  * generate the invoice will be stored in a database as integers, both to save space
  62.  * and to simplify calculations. So when a printable invoice is generated, your Web
  63.  * application will need to convert those integers into words, this is more clarity
  64.  * and more personality.
  65.  * 
  66.  * This class will accept almost any numeric value and convert it into an equivalent
  67.  * string of words in written Arabic language (using Windows-1256 character set).
  68.  * The value can be any positive number up to 999,999,999 (users should not use
  69.  * commas). It will take care of feminine and Arabic grammar rules.
  70.  *
  71.  * Example:
  72.  * <code>
  73.  *     include('./I18N/Arabic.php');
  74.  *     $obj = new I18N_Arabic('Numbers');
  75.  *     
  76.  *     $obj->setFeminine(1);
  77.  *     $obj->setFormat(1);
  78.  *     
  79.  *     $integer = 2147483647;
  80.  *     
  81.  *     $text = $obj->int2str($integer);
  82.  *     
  83.  *     echo "<p align=\"right\"><b class=hilight>$integer</b><br />$text</p>";
  84.  * 
  85.  *     $obj->setFeminine(2);
  86.  *     $obj->setFormat(2);
  87.  *     
  88.  *     $integer = 2147483647;
  89.  *     
  90.  *     $text = $obj->int2str($integer);
  91.  *     
  92.  *     echo "<p align=\"right\"><b class=hilight>$integer</b><br />$text</p>";
  93.  * </code>
  94.  *             
  95.  * @category  I18N
  96.  * @package   I18N_Arabic
  97.  * @author    Khaled Al-Sham'aa <khaled@ar-php.org>
  98.  * @copyright 2006-2012 Khaled Al-Sham'aa
  99.  *    
  100.  * @license   LGPL <http://www.gnu.org/licenses/lgpl.txt>
  101.  * @link      http://www.ar-php.org
  102.  */
  103.  
  104. // New in PHP V5.3: Namespaces
  105. // namespace I18N\Arabic;
  106. // 
  107. // $obj = new I18N\Arabic\Numbers();
  108. // 
  109. // use I18N\Arabic;
  110. // $obj = new Arabic\Numbers();
  111. //
  112. // use I18N\Arabic\Numbers as Numbers;
  113. // $obj = new Numbers();
  114.  
  115. /**
  116.  * This PHP class spell numbers in the Arabic idiom
  117.  *  
  118.  * @category  I18N
  119.  * @package   I18N_Arabic
  120.  * @author    Khaled Al-Sham'aa <khaled@ar-php.org>
  121.  * @copyright 2006-2012 Khaled Al-Sham'aa
  122.  *    
  123.  * @license   LGPL <http://www.gnu.org/licenses/lgpl.txt>
  124.  * @link      http://www.ar-php.org
  125.  */ 
  126. {
  127.     private $_individual    array();
  128.     private $_complications array();
  129.     private $_arabicIndic   array();
  130.     private $_ordering      array();
  131.     private $_feminine      1;
  132.     private $_format        1;
  133.     private $_order         1;
  134.  
  135.     /**
  136.      * Loads initialize values
  137.      *
  138.      * @ignore
  139.      */         
  140.     public function __construct()
  141.     {
  142.         $xml simplexml_load_file(dirname(__FILE__).'/data/ArNumbers.xml');
  143.  
  144.         foreach ($xml->xpath("//individual/number[@gender='male']"as $num{
  145.             if (isset($num['grammar'])) {
  146.                 $grammar $num['grammar'];
  147.                 
  148.                 $this->_individual["{$num['value']}"][1]["$grammar"= (string)$num;
  149.             else {
  150.                 $this->_individual["{$num['value']}"][1= (string)$num;
  151.             }
  152.         
  153.         
  154.         foreach ($xml->xpath("//individual/number[@gender='female']"as $num{
  155.             if (isset($num['grammar'])) {
  156.                 $grammar $num['grammar'];
  157.                 
  158.                 $this->_individual["{$num['value']}"][2]["$grammar"= (string)$num;
  159.             else {
  160.                 $this->_individual["{$num['value']}"][2= (string)$num;
  161.             }
  162.         
  163.         
  164.         foreach ($xml->xpath("//individual/number[@value>19]"as $num{
  165.             if (isset($num['grammar'])) {
  166.                 $grammar $num['grammar'];
  167.                 
  168.                 $this->_individual["{$num['value']}"]["$grammar"= (string)$num;
  169.             else {
  170.                 $this->_individual["{$num['value']}"= (string)$num;
  171.             }
  172.         
  173.         
  174.         foreach ($xml->complications->number as $num{
  175.             $scale  $num['scale'];
  176.             $format $num['format'];
  177.             
  178.             $this->_complications["$scale"]["$format"= (string)$num;
  179.         
  180.         
  181.         foreach ($xml->arabicIndic->number as $html{
  182.             $value  $html['value'];
  183.             
  184.             $this->_arabicIndic["$value"$html;
  185.         
  186.  
  187.         foreach ($xml->xpath("//order/number[@gender='male']"as $num{
  188.             $this->_ordering["{$num['value']}"][1= (string)$num;
  189.         
  190.  
  191.         foreach ($xml->xpath("//order/number[@gender='female']"as $num{
  192.             $this->_ordering["{$num['value']}"][2= (string)$num;
  193.         
  194.     }
  195.     
  196.     /**
  197.      * Set feminine flag of the counted object
  198.      *      
  199.      * @param integer $value Counted object feminine
  200.      *                       (1 for masculine & 2 for feminine)
  201.      *      
  202.      * @return object $this to build a fluent interface
  203.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  204.      */
  205.     public function setFeminine($value)
  206.     {
  207.         if ($value == || $value == 2{
  208.             $this->_feminine $value;
  209.         }
  210.         
  211.         return $this;
  212.     }
  213.     
  214.     /**
  215.      * Set the grammar position flag of the counted object
  216.      *      
  217.      * @param integer $value Grammar position of counted object
  218.      *                        (1 if Marfoua & 2 if Mansoub or Majrour)
  219.      *                            
  220.      * @return object $this to build a fluent interface
  221.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  222.      */
  223.     public function setFormat($value)
  224.     {
  225.         if ($value == || $value == 2{
  226.             $this->_format $value;
  227.         }
  228.         
  229.         return $this;
  230.     }
  231.     
  232.     /**
  233.      * Set the ordering flag, is it normal number or ordering number
  234.      *      
  235.      * @param integer $value Is it an ordering number? default is 1
  236.      *                        (use 1 if no and 2 if yes)
  237.      *                            
  238.      * @return object $this to build a fluent interface
  239.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  240.      */
  241.     public function setOrder($value)
  242.     {
  243.         if ($value == || $value == 2{
  244.             $this->_order $value;
  245.         }
  246.         
  247.         return $this;
  248.     }
  249.     
  250.     /**
  251.      * Get the feminine flag of counted object
  252.      *      
  253.      * @return integer return current setting of counted object feminine flag
  254.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  255.      */
  256.     public function getFeminine()
  257.     {
  258.         return $this->_feminine;
  259.     }
  260.     
  261.     /**
  262.      * Get the grammer position flag of counted object
  263.      *      
  264.      * @return integer return current setting of counted object grammer
  265.      *                  position flag
  266.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  267.      */
  268.     public function getFormat()
  269.     {
  270.         return $this->_format;
  271.     }
  272.     
  273.     /**
  274.      * Get the ordering flag value
  275.      *      
  276.      * @return integer return current setting of ordering flag value
  277.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  278.      */
  279.     public function getOrder()
  280.     {
  281.         return $this->_format;
  282.     }
  283.     
  284.     /**
  285.      * Spell integer number in Arabic idiom
  286.      *      
  287.      * @param integer $number The number you want to spell in Arabic idiom
  288.      *                    
  289.      * @return string The Arabic idiom that spells inserted number
  290.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  291.      */
  292.     public function int2str($number)
  293.     {
  294.         if ($number == && $this->_order == 2{
  295.             if ($this->_feminine == 1{
  296.                 $string 'الأول';
  297.             else {
  298.                 $string 'الأولى';
  299.             }
  300.         else {
  301.             if ($number 0{
  302.                 $string 'سالب ';
  303.                 $number = (string) -$number;
  304.             else {
  305.                 $string '';
  306.             }
  307.             
  308.             $temp explode('.'$number);
  309.  
  310.             $string .= $this->subInt2str($temp[0]);
  311.  
  312.             if (!empty($temp[1])) {
  313.                 $dec     $this->subInt2str($temp[1]);
  314.                 $string .= ' فاصلة ' $dec
  315.             }
  316.         }
  317.         
  318.         return $string;
  319.     }
  320.     
  321.     /**
  322.      * Spell integer number in Arabic idiom
  323.      *      
  324.      * @param integer $number The number you want to spell in Arabic idiom
  325.      * @param logical $zero   Present leading zero if true [default is true]
  326.      *      
  327.      * @return string The Arabic idiom that spells inserted number
  328.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  329.      */
  330.     protected function subInt2str($number$zero true)
  331.     {
  332.         $blocks array();
  333.         $items  array();
  334.         $zeros  '';
  335.         $string '';
  336.         $number ($zero != falsetrim($numbertrim((float)$number);
  337.         
  338.         if ($number 0{
  339.         
  340.             //--- by Jnom: handle left zero
  341.             // http://www.itkane.com
  342.             // jnom23@gmail.com
  343.             if ($zero != false{
  344.                 $fulnum $number;
  345.                 while (($fulnum[0]== '0'{
  346.                     $zeros 'صفر '.$zeros;
  347.                     $fulnum substr($fulnum1strlen($fulnum));
  348.                 };
  349.             };
  350.             //---/
  351.  
  352.             while (strlen($number3{
  353.                 array_push($blockssubstr($number-3));
  354.                 $number substr($number0strlen($number3);
  355.             }
  356.             array_push($blocks$number);
  357.             
  358.             $blocks_num count($blocks1;
  359.   
  360.             for ($i $blocks_num$i >= 0$i--{
  361.                 $number floor($blocks[$i]);
  362.   
  363.                 $text $this->writtenBlock($number);
  364.                 if ($text{
  365.                     if ($number == && $i != 0{
  366.                         $text $this->_complications[$i][4];
  367.                         if ($this->_order == 2{
  368.                             $text 'ال' $text;
  369.                         }
  370.                     elseif ($number == && $i != 0{
  371.                         $text $this->_complications[$i][$this->_format];
  372.                         if ($this->_order == 2{
  373.                             $text 'ال' $text;
  374.                         }
  375.                     elseif ($number && $number 11 && $i != 0{
  376.                         $text .= ' ' $this->_complications[$i][3];
  377.                         if ($this->_order == 2{
  378.                             $text 'ال' $text;
  379.                         }
  380.                     elseif ($i != 0{
  381.                         $text .= ' ' $this->_complications[$i][4];
  382.                         if ($this->_order == 2{
  383.                             $text 'ال' $text;
  384.                         }
  385.                     }
  386.                     
  387.                     //--- by Jnom: handle left zero
  388.                     if ($text != '' && $zeros != '' && $zero != false{
  389.                         $text  $zeros.' '.$text;
  390.                         $zeros '';
  391.                     };
  392.                     //---/
  393.  
  394.                     array_push($items$text);
  395.                 }
  396.             }
  397.             
  398.             $string implode(' و '$items);
  399.         else {
  400.             $string 'صفر';
  401.         }
  402.         return $string;
  403.     }
  404.     
  405.     /**
  406.      * Spell sub block number of three digits max in Arabic idiom
  407.      *      
  408.      * @param integer $number Sub block number of three digits max you want to
  409.      *                         spell in Arabic idiom
  410.      *                      
  411.      * @return string The Arabic idiom that spells inserted sub block
  412.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  413.      */
  414.     protected function writtenBlock($number)
  415.     {
  416.         $items  array();
  417.         $string '';
  418.         
  419.         if ($number 99{
  420.             $hundred floor($number 100100;
  421.             $number  $number 100;
  422.             
  423.             if ($this->_order == 2{
  424.                 $pre 'ال';
  425.             else {
  426.                 $pre '';
  427.             }
  428.             
  429.             if ($hundred == 200{
  430.                 array_push($items$pre.$this->_individual[$hundred][$this->_format]);
  431.             else {
  432.                 array_push($items$pre.$this->_individual[$hundred]);
  433.             }
  434.         }
  435.         
  436.         if ($number != 0{
  437.             if ($this->_order == 2{
  438.                 if ($number <= 10{
  439.                     array_push($items$this->_ordering[$number][$this->_feminine]);
  440.                 elseif ($number 20{
  441.                     $number -= 10;
  442.                     $item    'ال' $this->_ordering[$number][$this->_feminine];
  443.  
  444.                     if ($this->_feminine == 1{
  445.                         $item .= ' عشر';
  446.                     else {
  447.                         $item .= ' عشرة';
  448.                     }
  449.  
  450.                     array_push($items$item);
  451.                 else {
  452.                     $ones $number 10;
  453.                     $tens floor($number 1010;
  454.  
  455.                     array_push($items'ال' $this->_ordering[$ones][$this->_feminine]);
  456.                     array_push($items'ال' $this->_individual[$tens][$this->_format]);
  457.                 }
  458.             else {
  459.                 if ($number == || $number == 12{
  460.                     array_push($items$this->_individual[$number]
  461.                                                         [$this->_feminine]
  462.                                                         [$this->_format]);
  463.                 elseif ($number 20{
  464.                     array_push($items$this->_individual[$number][$this->_feminine]);
  465.                 else {
  466.                     $ones $number 10;
  467.                     $tens floor($number 1010;
  468.                     
  469.                     if ($ones == 2{
  470.                         array_push($items$this->_individual[$ones]
  471.                                                             [$this->_feminine]
  472.                                                             [$this->_format]);
  473.                     elseif ($ones 0{
  474.                         array_push($items$this->_individual[$ones][$this->_feminine]);
  475.                     }
  476.                     
  477.                     array_push($items$this->_individual[$tens][$this->_format]);
  478.                 }
  479.             }
  480.         }
  481.         
  482.         $items  array_diff($itemsarray(''));
  483.         $string implode(' و '$items);
  484.         
  485.         return $string;
  486.     }
  487.  
  488.     
  489.     /**
  490.      * Represent integer number in Arabic-Indic digits using HTML entities
  491.      *      
  492.      * @param integer $number The number you want to present in Arabic-Indic digits
  493.      *                         using HTML entities
  494.      *                    
  495.      * @return string The Arabic-Indic digits represent inserted integer number using
  496.      *                 HTML entities
  497.      * @author Khaled Al-Sham'aa <khaled@ar-php.org>
  498.      */
  499.     public function int2indic($number)
  500.     {
  501.         $str strtr("$number"$this->_arabicIndic);
  502.  
  503.         return $str;
  504.     }
  505. }

Documentation generated on Wed, 29 Aug 2012 08:33:10 +0200 by phpDocumentor 1.4.0