eZ Publish  [4.0]
eztemplateunitoperator.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZTemplateUnitOperator class
00004 //
00005 // Created on: <09-Apr-2002 11:14:30 amos>
00006 //
00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00008 // SOFTWARE NAME: eZ Publish
00009 // SOFTWARE RELEASE: 4.0.x
00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00011 // SOFTWARE LICENSE: GNU General Public License v2.0
00012 // NOTICE: >
00013 //   This program is free software; you can redistribute it and/or
00014 //   modify it under the terms of version 2.0  of the GNU General
00015 //   Public License as published by the Free Software Foundation.
00016 //
00017 //   This program is distributed in the hope that it will be useful,
00018 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //   GNU General Public License for more details.
00021 //
00022 //   You should have received a copy of version 2.0 of the GNU General
00023 //   Public License along with this program; if not, write to the Free
00024 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 //   MA 02110-1301, USA.
00026 //
00027 //
00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00029 //
00030 
00031 /*!
00032   \class eZTemplateUnitOperator eztemplateunitoperator.php
00033   \ingroup eZTemplateOperators
00034   \brief Handles unit conversion and display using the operator "si"
00035 
00036   The operator reads two parameters. The first tells the kind of unit type
00037   we're dealing with, for instance: byte, length.
00038   The second determines the behaviour of prefixes and is optional.
00039 
00040   The available units are defined in the settings/unit.ini file. The bases
00041   are read from the Base group.
00042 
00043   The unit operator supports both traditional 10^n based prefixes as well
00044   as binary prefixes(2^n n=10,20..), both old names and new names.
00045   See <a href="http://physics.nist.gov/cuu/Units/">International Systems of Units</a>
00046 
00047 \code
00048 // Example of template code
00049 {1025|si(byte)}
00050 {1025|si(byte,binary)}
00051 {1025|si(byte,decimal)}
00052 {1025|si(byte,none)}
00053 {1025|si(byte,auto)}
00054 {1025|si(byte,mebi)}
00055 \endcode
00056 */
00057 
00058 //include_once( "lib/ezutils/classes/ezini.php" );
00059 
00060 class eZTemplateUnitOperator
00061 {
00062     /*!
00063      Initializes the operator with the name $name, default is "si"
00064     */
00065     function eZTemplateUnitOperator( $name = "si" )
00066     {
00067         $this->SIName = $name;
00068         $this->Operators = array( $name );
00069     }
00070 
00071     /*!
00072      Returns the operators in this class.
00073     */
00074     function operatorList()
00075     {
00076         return $this->Operators;
00077     }
00078 
00079     function operatorTemplateHints()
00080     {
00081         return array( $this->SIName => array( 'input' => true,
00082                                               'output' => true,
00083                                               'parameters' => true,
00084                                               'element-transformation' => true,
00085                                               'transform-parameters' => true,
00086                                               'input-as-parameter' => 'always',
00087                                               'element-transformation-func' => 'operatorTransform' ) );
00088     }
00089 
00090     /*!
00091       \reimp
00092     */
00093     function operatorTransform( $operatorName, &$node, $tpl, &$resourceData,
00094                                 $element, $lastElement, $elementList, $elementTree, &$parameters )
00095     {
00096         if ( !eZTemplateNodeTool::isStaticElement( $parameters[1] ) ||
00097              ( count( $parameters ) > 2 && !eZTemplateNodeTool::isStaticElement( $parameters[2] ) ) )
00098         {
00099             return false;
00100         }
00101 
00102         // We do not support non-static values for decimal_count, decimal_symbol and thousands_separator
00103         if ( count( $parameters ) > 3 and
00104              !eZTemplateNodeTool::isStaticElement( $parameters[3] ) )
00105             return false;
00106         if ( count( $parameters ) > 4 and
00107              !eZTemplateNodeTool::isStaticElement( $parameters[4] ) )
00108             return false;
00109         if ( count( $parameters ) > 5 and
00110              !eZTemplateNodeTool::isStaticElement( $parameters[5] ) )
00111             return false;
00112 
00113         //include_once( 'lib/ezlocale/classes/ezlocale.php' );
00114         $locale = eZLocale::instance();
00115         $decimalCount = $locale->decimalCount();
00116         $decimalSymbol = $locale->decimalSymbol();
00117         $decimalThousandsSeparator = $locale->thousandsSeparator();
00118 
00119         if ( count( $parameters ) > 2 )
00120         {
00121             $prefix = eZTemplateNodeTool::elementStaticValue( $parameters[2] );
00122         }
00123         else
00124         {
00125             $prefix = 'auto';
00126         }
00127 
00128         if ( count( $parameters ) > 3 )
00129             $decimalCount = eZTemplateNodeTool::elementStaticValue( $parameters[3] );
00130         elseif ( $prefix == 'none' )
00131             $decimalCount = 0;
00132 
00133         if ( count( $parameters ) > 4 )
00134             $decimalSymbol = eZTemplateNodeTool::elementStaticValue( $parameters[4] );
00135         if ( count( $parameters ) > 5 )
00136             $decimalThousandsSeparator = eZTemplateNodeTool::elementStaticValue( $parameters[5] );
00137 
00138         $decimalSymbolText = eZPHPCreator::variableText( $decimalSymbol, 0, 0, false );
00139         $decimalThousandsSeparatorText = eZPHPCreator::variableText( $decimalThousandsSeparator, 0, 0, false );
00140 
00141         $unit = eZTemplateNodeTool::elementStaticValue( $parameters[1] );
00142 
00143         $ini = eZINI::instance();
00144         if ( $prefix == "auto" )
00145         {
00146             $prefixes = $ini->variableArray( "UnitSettings", "BinaryUnits" );
00147             if ( in_array( $unit, $prefixes ) )
00148                 $prefix = "binary";
00149             else
00150                 $prefix = "decimal";
00151         }
00152 
00153         $unit_ini = eZINI::instance( "units.ini" );
00154         $use_si = $ini->variable( "UnitSettings", "UseSIUnits" ) == "true";
00155         $fake = $use_si ? "" : "Fake";
00156         if ( $unit_ini->hasVariable( "Base", $unit ) )
00157         {
00158             $base = $unit_ini->variable( "Base", $unit );
00159         }
00160 
00161         $hasInput = false;
00162         $output = false;
00163         if ( eZTemplateNodeTool::isStaticElement( $parameters[0] ) )
00164         {
00165             $output = eZTemplateNodeTool::elementStaticValue( $parameters[0] );
00166             $hasInput = true;
00167         }
00168 
00169         $prefix_var = "";
00170         if ( $prefix == "decimal" )
00171         {
00172             $prefixes = $unit_ini->group( "DecimalPrefixes" );
00173 
00174             $prefix_group = $unit_ini->group( "DecimalPrefixes" );
00175             $prefixes = array();
00176             foreach ( $prefix_group as $prefix_item )
00177             {
00178                 $prefixes[] = explode( ";", $prefix_item );
00179             }
00180             usort( $prefixes, "eZTemplateUnitCompareFactor" );
00181             $prefix_var = "";
00182 
00183             if ( $hasInput )
00184             {
00185                 if ( $output >= 0 and $output < 10 )
00186                 {
00187                     $prefix_var = '';
00188                 }
00189                 else
00190                 {
00191                     foreach ( $prefixes as $prefix )
00192                     {
00193                         $val = pow( 10, (int)$prefix[0] );
00194                         if ( $val <= $output )
00195                         {
00196                             $prefix_var = $prefix[1];
00197                             $output = number_format( $output / $val, $decimalCount, $decimalSymbol, $decimalThousandsSeparator );
00198                             break;
00199                         }
00200                     }
00201                 }
00202             }
00203             else
00204             {
00205                 $values = array();
00206                 $values[] = $parameters[0];
00207                 $values[] = array( eZTemplateNodeTool::createArrayElement( $prefixes ) );
00208                 $values[] = array( eZTemplateNodeTool::createStringElement( $base ) );
00209 
00210                 $code = 'if ( %1% >= 0 and %1% < 10 )' . "\n" .
00211                      '{' . "\n" .
00212                      '    %tmp3% = \'\';' . "\n" .
00213                      '}' . "\n" .
00214                      'else' . "\n" .
00215                      '{' . "\n" .
00216                      '    %tmp3% = "";' . "\n" .
00217                      '    foreach ( %2% as %tmp1% )' . "\n" .
00218                      '    {' . "\n" .
00219                      '        %tmp2% = pow( 10, (int)%tmp1%[0] );' . "\n" .
00220                      '        if ( %tmp2% <= %1% )' . "\n" .
00221                      '        {' . "\n" .
00222                      '            %tmp3% = %tmp1%[1];' . "\n" .
00223                      '            %1% = number_format( %1% / %tmp2%, ' . $decimalCount . ', ' . $decimalSymbolText . ', ' . $decimalThousandsSeparatorText . ' );' . "\n" .
00224                      '            break;' . "\n" .
00225                      '        }' . "\n" .
00226                      '    }' . "\n" .
00227                      '}' . "\n" .
00228                      '%output% = %1% . \' \' . %tmp3% . %3%;';
00229 
00230                 return array( eZTemplateNodeTool::createCodePieceElement( $code, $values, false, 3 ) );
00231             }
00232         }
00233         else if ( $prefix == "binary" )
00234         {
00235             $prefix_group = $unit_ini->group( $fake . "BinaryPrefixes" );
00236             $prefixes = array();
00237             foreach ( $prefix_group as $prefix_item )
00238             {
00239                 $prefixes[] = explode( ";", $prefix_item );
00240             }
00241             usort( $prefixes, "eZTemplateUnitCompareFactor" );
00242             $prefix_var = "";
00243 
00244             if ( $hasInput )
00245             {
00246                 if ( $output >= 0 and $output < 10 )
00247                 {
00248                     $prefix_var = '';
00249                 }
00250                 {
00251                     foreach ( $prefixes as $prefix )
00252                     {
00253                         $val = pow( 2, (int)$prefix[0] );
00254                         if ( $val <= $output )
00255                         {
00256                             $prefix_var = $prefix[1];
00257                             $output = number_format( $output / $val, $decimalCount, $decimalSymbol, $decimalThousandsSeparator );
00258                             break;
00259                         }
00260                     }
00261                 }
00262             }
00263             else
00264             {
00265                 $values = array();
00266                 $values[] = $parameters[0];
00267                 $values[] = array( eZTemplateNodeTool::createArrayElement( $prefixes ) );
00268                 $values[] = array( eZTemplateNodeTool::createStringElement( $base ) );
00269 
00270                 $code = 'if ( %1% >= 0 and %1% < 10 )' . "\n" .
00271                      '{' . "\n" .
00272                      '    %tmp3% = \'\';' . "\n" .
00273                      '}' . "\n" .
00274                      'else' . "\n" .
00275                      '{' . "\n" .
00276                      '    %tmp3% = "";' . "\n" .
00277                      '    foreach ( %2% as %tmp1% )' . "\n" .
00278                      '    {' . "\n" .
00279                      '      %tmp2% = pow( 2, (int)%tmp1%[0] );' . "\n" .
00280                      '      if ( %tmp2% <= %1% )' . "\n" .
00281                      '      {' . "\n" .
00282                      '        %tmp3% = %tmp1%[1];' . "\n" .
00283                      '        %1% = number_format( %1% / %tmp2%, ' . $decimalCount . ', ' . $decimalSymbolText . ', ' . $decimalThousandsSeparatorText . ' );' . "\n" .
00284                      '        break;' . "\n" .
00285                      '      }' . "\n" .
00286                      '    }' . "\n" .
00287                      '}' . "\n" .
00288                      '%output% = %1% . \' \' . %tmp3% . %3%;';
00289 
00290                 return array( eZTemplateNodeTool::createCodePieceElement( $code, $values, false, 3 ) );
00291             }
00292         }
00293         else
00294         {
00295             if ( $unit_ini->hasVariable( "BinaryPrefixes", $prefix ) )
00296             {
00297                 $prefix_base = 2;
00298                 $prefix_var = $unit_ini->variableArray( "BinaryPrefixes", $prefix );
00299             }
00300             else if ( $unit_ini->hasVariable( "DecimalPrefixes", $prefix ) )
00301             {
00302                 $prefix_base = 10;
00303                 $prefix_var = $unit_ini->variableArray( "DecimalPrefixes", $prefix );
00304             }
00305             else if ( $prefix == "none" )
00306             {
00307                 $prefix_var = '';
00308                 if ( $hasInput )
00309                 {
00310                     $output = number_format( $output, $decimalCount, $decimalSymbol, $decimalThousandsSeparator );
00311                 }
00312                 else
00313                 {
00314                     $values = array();
00315                     $values[] = $parameters[0];
00316                     $values[] = array( eZTemplateNodeTool::createStringElement( '' ) );
00317                     $values[] = array( eZTemplateNodeTool::createStringElement( $base ) );
00318 
00319                     $code = '%output% = number_format( %1%, ' . $decimalCount . ', ' . $decimalSymbolText . ', ' . $decimalThousandsSeparatorText . ' ) . \' \' . %2% . %3%;';
00320 
00321                     return array( eZTemplateNodeTool::createCodePieceElement( $code, $values ) );
00322                 }
00323             }
00324 
00325             if ( is_array( $prefix_var ) )
00326             {
00327                 if ( $hasInput )
00328                 {
00329                     $val = pow( $prefix_base, (int)$prefix_var[0] );
00330                     $output = number_format( $output / $val, $decimalCount, $decimalSymbol, $decimalThousandsSeparator );
00331                     $prefix_var = $prefix_var[1];
00332                 }
00333                 else
00334                 {
00335                     $values = array();
00336                     $values[] = $parameters[0];
00337                     $values[] = array( eZTemplateNodeTool::createNumericElement( pow( $prefix_base, (int)$prefix_var[0] ) ) );
00338                     $values[] = array( eZTemplateNodeTool::createStringElement( $prefix_var[1] ) );
00339                     $values[] = array( eZTemplateNodeTool::createStringElement( $base ) );
00340 
00341                     $code = '%output% = number_format( %1% / %2%, ' . $decimalCount . ', ' . $decimalSymbolText . ', ' . $decimalThousandsSeparatorText . ' ) . \' \' . %3% . %4%;';
00342 
00343                     return array( eZTemplateNodeTool::createCodePieceElement( $code, $values ) );
00344                 }
00345             }
00346         }
00347 
00348         if ( $hasInput )
00349         {
00350             return array( eZTemplateNodeTool::createStringElement( $output . ' ' . $prefix_var . $base ) );
00351         }
00352 
00353         $values = array();
00354         $values[] = $parameters[0];
00355         $values[] = array( eZTemplateNodeTool::createStringElement( $prefix_var ) );
00356         $values[] = array( eZTemplateNodeTool::createStringElement( $base ) );
00357 
00358         $code = '%output% = %1% . \' \' . %2% . %3%;';
00359 
00360         return array( eZTemplateNodeTool::createCodePieceElement( $code, $values ) );
00361     }
00362 
00363     /*!
00364      See eZTemplateOperator::namedParameterList
00365     */
00366     function namedParameterList()
00367     {
00368         return array( "unit" => array( "type" => "string",
00369                                        "required" => true,
00370                                        "default" => false ),
00371                       "prefix" => array( "type" => "string",
00372                                          "required" => false,
00373                                          "default" => "auto" ),
00374                       "decimal_count" => array( "type" => "integer",
00375                                                 "required" => false,
00376                                                 "default" => false ),
00377                       "decimal_symbol" => array( "type" => "string",
00378                                                  "required" => false,
00379                                                  "default" => false ),
00380                       "thousands_separator" => array( "type" => "string",
00381                                                       "required" => false,
00382                                                       "default" => false ) );
00383     }
00384 
00385     /*!
00386      Performs unit conversion.
00387     */
00388     function modify( $tpl, $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, &$operatorValue, $namedParameters,
00389                      $placement )
00390     {
00391         $unit = $namedParameters["unit"];
00392         $prefix = $namedParameters["prefix"];
00393 
00394         //include_once( 'lib/ezlocale/classes/ezlocale.php' );
00395         $locale = eZLocale::instance();
00396         $decimalCount = $locale->decimalCount();
00397         $decimalSymbol = $locale->decimalSymbol();
00398         $decimalThousandsSeparator = $locale->thousandsSeparator();
00399 
00400         if ( $namedParameters['decimal_count'] !== false )
00401             $decimalCount = $namedParameters['decimal_count'];
00402         elseif ( $prefix == 'none' )
00403             $decimalCount = 0;
00404 
00405         if ( strlen( $namedParameters['decimal_symbol'] ) > 0 )
00406             $decimalSymbol = $namedParameters['decimal_symbol'];
00407         if ( strlen( $namedParameters['thousands_separator'] ) > 0 )
00408             $decimalThousandsSeparator = $namedParameters['thousands_separator'];
00409 
00410         $ini = eZINI::instance();
00411         if ( $prefix == "auto" )
00412         {
00413             $prefixes = $ini->variableArray( "UnitSettings", "BinaryUnits" );
00414             if ( in_array( $unit, $prefixes ) )
00415                 $prefix = "binary";
00416             else
00417                 $prefix = "decimal";
00418         }
00419         $unit_ini = eZINI::instance( "units.ini" );
00420         $use_si = $ini->variable( "UnitSettings", "UseSIUnits" ) == "true";
00421         $fake = $use_si ? "" : "Fake";
00422         if ( $unit_ini->hasVariable( "Base", $unit ) )
00423         {
00424             $base = $unit_ini->variable( "Base", $unit );
00425         }
00426         else
00427         {
00428             $tpl->warning( "eZTemplateUnitOperator", "No such unit '$unit'", $placement );
00429             return;
00430         }
00431         $prefix_var = "";
00432         if ( $prefix == "decimal" )
00433         {
00434             if ( $operatorValue >= 0 and $operatorValue < 10 )
00435             {
00436                 $prefix_var = '';
00437             }
00438             else
00439             {
00440                 $prefix_group = $unit_ini->group( "DecimalPrefixes" );
00441                 $prefixes = array();
00442                 foreach ( $prefix_group as $prefix_item )
00443                 {
00444                     $prefixes[] = explode( ";", $prefix_item );
00445                 }
00446                 usort( $prefixes, "eZTemplateUnitCompareFactor" );
00447                 $prefix_var = "";
00448                 $divider = false;
00449                 foreach ( $prefixes as $prefix )
00450                 {
00451                     $val = pow( 10, (int)$prefix[0] );
00452                     if ( $val <= $operatorValue )
00453                     {
00454                         $prefix_var = $prefix[1];
00455                         $operatorValue = number_format( $operatorValue / $val, $decimalCount, $decimalSymbol, $decimalThousandsSeparator );
00456                         break;
00457                     }
00458                 }
00459             }
00460         }
00461         else if ( $prefix == "binary" )
00462         {
00463             if ( $operatorValue >= 0 and $operatorValue < 10 )
00464             {
00465                 $prefix_var = '';
00466             }
00467             else
00468             {
00469                 $prefix_group = $unit_ini->group( $fake . "BinaryPrefixes" );
00470                 $prefixes = array();
00471                 foreach ( $prefix_group as $prefix_item )
00472                 {
00473                     $prefixes[] = explode( ";", $prefix_item );
00474                 }
00475                 usort( $prefixes, "eZTemplateUnitCompareFactor" );
00476                 $prefix_var = "";
00477                 foreach ( $prefixes as $prefix )
00478                 {
00479                     $val = pow( 2, (int)$prefix[0] );
00480                     if ( $val <= $operatorValue )
00481                     {
00482                         $prefix_var = $prefix[1];
00483                         $operatorValue = number_format( $operatorValue / $val, $decimalCount, $decimalSymbol, $decimalThousandsSeparator );
00484                         break;
00485                     }
00486                 }
00487             }
00488         }
00489         else
00490         {
00491             if ( $unit_ini->hasVariable( "BinaryPrefixes", $prefix ) )
00492             {
00493                 $prefix_base = 2;
00494                 $prefix_var = $unit_ini->variableArray( "BinaryPrefixes", $prefix );
00495             }
00496             else if ( $unit_ini->hasVariable( "DecimalPrefixes", $prefix ) )
00497             {
00498                 $prefix_base = 10;
00499                 $prefix_var = $unit_ini->variableArray( "DecimalPrefixes", $prefix );
00500             }
00501             else if ( $prefix == "none" )
00502             {
00503                 $prefix_var = "";
00504                 $operatorValue = number_format( $operatorValue, $decimalCount, $decimalSymbol, $decimalThousandsSeparator );
00505             }
00506             else
00507                 $tpl->warning( $operatorName, "Prefix \"$prefix\" for unit \"$unit\" not found", $placement );
00508             if ( is_array( $prefix_var ) )
00509             {
00510                 $val = pow( $prefix_base, (int)$prefix_var[0] );
00511                 $operatorValue = number_format( $operatorValue / $val, $decimalCount, $decimalSymbol, $decimalThousandsSeparator );
00512                 $prefix_var = $prefix_var[1];
00513             }
00514         }
00515         $operatorValue = "$operatorValue $prefix_var" . $base;
00516     }
00517 
00518 }
00519 
00520 /*!
00521  Helper function for eZTemplateUnitOperator which sorts array elements.
00522  Sorts on index 0 of $a and $b.
00523 */
00524     function eZTemplateUnitCompareFactor( $a, $b )
00525     {
00526         if ( $a[0] == $b[0] )
00527             return 0;
00528         return ( $a[0] > $b[0] ) ? -1 : 1;
00529     }
00530 ?>