00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 define( 'EZ_CHARTRANSFORM_CODEDATE', 1177423380 );
00046 include_once( 'lib/ezi18n/classes/eztextcodec.php' );
00047 include_once( 'lib/ezi18n/classes/ezcharsetinfo.php' );
00048
00049 class eZCharTransform
00050 {
00051
00052
00053
00054 function eZCharTransform()
00055 {
00056 $this->Mapper = false;
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 function transform( $text, $rule, $charset = false, $useCache = true )
00068 {
00069 if ( $useCache )
00070 {
00071
00072 include_once( 'lib/ezutils/classes/ezsys.php' );
00073 $key = eZSys::ezcrc32( 'Rule: ' . ( is_array( $rule ) ? implode( ',', $rule ) : $rule ) . '-' . $charset );
00074
00075 $charsetName = ( $charset === false ? eZTextCodec::internalCharset() : eZCharsetInfo::realCharsetCode( $charset ) );
00076
00077
00078
00079 if ( $this->executeCacheFile( $text,
00080 'rule-', '-' . $charsetName,
00081 $key, false, $filepath ) )
00082 {
00083
00084 return $text;
00085 }
00086 }
00087
00088
00089 if ( $this->Mapper === false )
00090 {
00091 include_once( 'lib/ezi18n/classes/ezcodemapper.php' );
00092 $this->Mapper = new eZCodeMapper();
00093 }
00094
00095 $this->Mapper->loadTransformationFiles( $charsetName, false );
00096
00097
00098 $unicodeTable = $this->Mapper->generateMappingCode( $rule );
00099
00100
00101 $charsetTable = $this->Mapper->generateCharsetMappingTable( $unicodeTable, $charset );
00102 $transformationData = array( 'table' => $charsetTable );
00103 unset( $unicodeTable );
00104
00105 if ( $useCache )
00106 {
00107 $extraCode = '';
00108 $this->storeCacheFile( $filepath, $transformationData,
00109 $extraCode,
00110 'Rule', $charsetName );
00111 }
00112
00113
00114 return strtr( $text, $transformationData['table'] );
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 function transformByGroup( $text, $group, $charset = false, $useCache = true )
00126 {
00127 $charsetName = ( $charset === false ? eZTextCodec::internalCharset() : eZCharsetInfo::realCharsetCode( $charset ) );
00128 if ( $useCache )
00129 {
00130
00131 include_once( 'lib/ezutils/classes/ezsys.php' );
00132
00133 $keyText = 'Group:' . $group;
00134 $key = eZSys::ezcrc32( $keyText . '-' . $charset );
00135
00136
00137
00138 if ( $this->executeCacheFile( $text,
00139 'g-' . $group . '-', '-' . $charsetName,
00140 $key, false, $filepath ) )
00141 {
00142
00143 return $text;
00144 }
00145 }
00146
00147 $commands = $this->groupCommands( $group );
00148 if ( $commands === false )
00149 return false;
00150
00151
00152 if ( $this->Mapper === false )
00153 {
00154 include_once( 'lib/ezi18n/classes/ezcodemapper.php' );
00155 $this->Mapper = new eZCodeMapper();
00156 }
00157
00158 $this->Mapper->loadTransformationFiles( $charsetName, $group );
00159
00160 $rules = array();
00161 foreach ( $commands as $command )
00162 {
00163 $rules = array_merge( $rules,
00164 $this->Mapper->decodeCommand( $command['command'], $command['parameters'] ) );
00165 }
00166
00167
00168 $unicodeTable = $this->Mapper->generateMappingCode( $rules );
00169
00170
00171 $charsetTable = $this->Mapper->generateCharsetMappingTable( $unicodeTable, $charset );
00172 $transformationData = array( 'table' => $charsetTable );
00173 unset( $unicodeTable );
00174
00175 if ( $useCache )
00176 {
00177 $extraCode = '';
00178 foreach ( $commands as $command )
00179 {
00180 $code = $this->Mapper->generateCommandCode( $command, $charsetName );
00181 if ( $code !== false )
00182 {
00183 $extraCode .= $code . "\n";
00184 }
00185 }
00186 $this->storeCacheFile( $filepath, $transformationData,
00187 $extraCode,
00188 'Group:' . $group, $charsetName );
00189 }
00190
00191
00192 $text = strtr( $text, $transformationData['table'] );
00193
00194
00195 foreach ( $commands as $command )
00196 {
00197 $this->Mapper->executeCommandCode( $text, $command, $charsetName );
00198 }
00199
00200 return $text;
00201 }
00202
00203
00204
00205
00206
00207
00208 function cachedTransformationPath()
00209 {
00210 $dir =& $GLOBALS['eZCodeMapperCachePath'];
00211 if ( isset( $dir ) )
00212 return $dir;
00213
00214 include_once( 'lib/ezutils/classes/ezsys.php' );
00215 $sys =& eZSys::instance();
00216 $dir = $sys->cacheDirectory() . '/trans';
00217 return $dir;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 function groupCommands( $group )
00231 {
00232 $rules =& $this->GroupRules[$group];
00233 if ( isset( $rules ) )
00234 return $rules;
00235
00236 $ini =& eZINI::instance( 'transform.ini' );
00237 $groups = $ini->variable( 'Transformation', 'Groups' );
00238 if ( !in_array( $group, $groups ) )
00239 {
00240 eZDebug::writeError( "Transformation group $group is not part of the active group list Groups in transform.ini",
00241 'eZCharTransform::groupCommands' );
00242 return false;
00243 }
00244
00245 if ( !$ini->hasGroup( $group ) )
00246 {
00247 eZDebug::writeError( "Transformation group $group is missing in transform.ini",
00248 'eZCharTransform::groupCommands' );
00249 return false;
00250 }
00251
00252 $rules = array();
00253 $ruleTexts = $ini->variable( $group, 'Commands' );
00254 foreach ( $ruleTexts as $ruleText )
00255 {
00256 if ( preg_match( "#^([a-zA-Z][a-zA-Z0-9_-]+)(\((.+)\))?$#", $ruleText, $matches ) )
00257 {
00258 $command = $matches[1];
00259 $parameters = array();
00260 if ( isset( $matches[2] ) )
00261 {
00262 $parameters = explode( ',', $matches[3] );
00263 }
00264 $rules[] = array( 'command' => $command,
00265 'parameters' => $parameters );
00266 }
00267 }
00268
00269 return $rules;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 function executeCacheFile( &$text, $prefix, $suffix, $key, $timestamp = false, &$filepath )
00284 {
00285 $path = eZCharTransform::cachedTransformationPath();
00286 if ( !file_exists( $path ) )
00287 {
00288 include_once( 'lib/ezfile/classes/ezdir.php' );
00289 eZDir::mkdir( $path, false, true );
00290 }
00291 $filepath = $path . '/' . $prefix . sprintf( "%u", $key ) . $suffix . '.ctt.php';
00292 if ( file_exists( $filepath ) )
00293 {
00294 $time = filemtime( $filepath );
00295 if ( $time >= max( EZ_CHARTRANSFORM_CODEDATE, $timestamp ) )
00296 {
00297
00298 include( $filepath );
00299 return true;
00300 }
00301 }
00302 return false;
00303 }
00304
00305
00306
00307
00308
00309 function storeCacheFile( $filepath, $transformationData,
00310 $extraCode, $type, $charsetName )
00311 {
00312 $fd = @fopen( $filepath, 'wb' );
00313 if ( $fd )
00314 {
00315 @fwrite( $fd, "<?" . "php\n" );
00316 @fwrite( $fd, "// Cached transformation data\n" );
00317 @fwrite( $fd, "// Type: $type\n" );
00318 @fwrite( $fd, "// Charset: $charsetName\n" );
00319 @fwrite( $fd, "// Cached transformation data\n" );
00320
00321
00322 @fwrite( $fd, '$data = ' . eZCharTransform::varExport( $transformationData ) . ";\n" );
00323 @fwrite( $fd, "\$text = strtr( \$text, \$data['table'] );\n" );
00324
00325 if ( $extraCode )
00326 {
00327 @fwrite( $fd, $extraCode );
00328 }
00329
00330 @fwrite( $fd, "?>" );
00331 @fclose( $fd );
00332 }
00333 else
00334 {
00335 eZDebug::writeError( "Failed to store transformation table $filepath" );
00336 }
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 function varExport( $value )
00358 {
00359 $ver = phpversion();
00360
00361
00362
00363
00364
00365 if ( version_compare( $ver, '4.3.5' ) < 0 or
00366 ( version_compare( $ver, '4.3.10' ) >= 0 and
00367 version_compare( $ver, '4.3.11' ) < 0 ) )
00368 {
00369 return eZCharTransform::varExportInternal( $value );
00370 }
00371 else
00372 {
00373 return var_export( $value, true );
00374 }
00375 }
00376
00377
00378
00379
00380
00381 function varExportInternal( $value, $column = 0, $iteration = 0 )
00382 {
00383
00384 if ( is_bool( $value ) )
00385 $text = ( $value ? 'true' : 'false' );
00386 else if ( is_null( $value ) )
00387 $text = 'null';
00388 else if ( is_string( $value ) )
00389 {
00390 $valueText = str_replace( array( "\\",
00391 "\"",
00392 "\$",
00393 "\n" ),
00394 array( "\\\\",
00395 "\\\"",
00396 "\\$",
00397 "\\n" ),
00398 $value );
00399 $text = "\"$valueText\"";
00400 }
00401 else if ( is_numeric( $value ) )
00402 $text = $value;
00403 else if ( is_object( $value ) )
00404 {
00405 $text = '';
00406 if ( method_exists( $value, 'serializedata' ) )
00407 {
00408 $serializeData = $value->serializeData();
00409 $className = $serializeData['class_name'];
00410 $text = "new $className(";
00411
00412 $column += strlen( $text );
00413 $parameters = $serializeData['parameters'];
00414 $variables = $serializeData['variables'];
00415
00416 $i = 0;
00417 foreach ( $parameters as $parameter )
00418 {
00419 if ( $i > 0 )
00420 {
00421 $text .= ",\n" . str_repeat( ' ', $column );
00422 }
00423 $variableName = $variables[$parameter];
00424 $variableValue = $value->$variableName;
00425 $keyText = " ";
00426 $text .= $keyText . eZCharTransform::varExportInternal( $variableValue, $column + strlen( $keyText ), $iteration + 1 );
00427 ++$i;
00428 }
00429 if ( $i > 0 )
00430 $text .= ' ';
00431
00432 $text .= ')';
00433 }
00434 }
00435 else if ( is_array( $value ) )
00436 {
00437 $text = 'array(';
00438 $column += strlen( $text );
00439 $valueKeys = array_keys( $value );
00440 $isIndexed = true;
00441 for ( $i = 0; $i < count( $valueKeys ); ++$i )
00442 {
00443 if ( $i !== $valueKeys[$i] )
00444 {
00445 $isIndexed = false;
00446 break;
00447 }
00448 }
00449 $i = 0;
00450 foreach ( $valueKeys as $key )
00451 {
00452 if ( $i > 0 )
00453 {
00454 $text .= ",\n" . str_repeat( ' ', $column );
00455 }
00456 $element =& $value[$key];
00457 $keyText = ' ';
00458 if ( !$isIndexed )
00459 {
00460 if ( is_int( $key ) )
00461 $keyText = $key;
00462 else
00463 $keyText = "\"" . str_replace( array( "\\",
00464 "\"",
00465 "\n" ),
00466 array( "\\\\",
00467 "\\\"",
00468 "\\n" ),
00469 $key ) . "\"";
00470 $keyText = " $keyText => ";
00471 }
00472 $text .= $keyText . eZCharTransform::varExportInternal( $element, $column + strlen( $keyText ), $iteration + 1 );
00473 ++$i;
00474 }
00475 if ( $i > 0 )
00476 $text .= ' ';
00477 $text .= ')';
00478 }
00479 else
00480 $text = 'null';
00481 return $text;
00482 }
00483
00484
00485
00486
00487 function &instance()
00488 {
00489 $instance =& $GLOBALS['eZCharTransformInstance'];
00490 if ( !isset( $instance ) )
00491 {
00492 $instance = new eZCharTransform();
00493 }
00494 return $instance;
00495 }
00496 }
00497
00498 ?>