Exponential Basic 2.4.0.1 Exponential Basic CMS — PHP Class Reference

ezcodemapper.php
Go to the documentation of this file.
1 <?php
19 class eZCodeMapper
20 {
21 const TYPE_DIRECT = 1;
22 const TYPE_RANGE = 2;
23 const TYPE_REPLACE = 3;
24
25 public function __construct()
26 {
27 $this->TransformationTables = array();
28 $this->TransformationFiles = array();
29 }
30
34 function mappingTable( $identifier )
35 {
36 if ( isset( $this->TransformationTables[$identifier] ) )
37 return $this->TransformationTables[$identifier];
38 return false;
39 }
40
44 function ruleNames()
45 {
46 return array_keys( $this->TransformationTables );
47 }
48
52 function error( $text, $position = false )
53 {
54 if ( $position )
55 {
56 $str = $position['file'] . ':' . $position['from'][0] . ' C' . $position['from'][1];
57 if ( isset( $position['to'] ) )
58 $str .= ' -> L' . $position['to'][0] . ' C' . $position['to'][1];
59 $str .= ':';
60 }
61 $str .= $text;
62 if ( class_exists( 'ezcli' ) )
63 {
64 $cli = eZCLI::instance();
65 $cli->error( $str );
66 }
67 else
68 {
69 eZDebug::writeError( $str, __METHOD__ );
70 }
71 }
72
76 function warning( $text, $position = false )
77 {
78 if ( $position )
79 {
80 $str = $position['file'] . ':' . $position['from'][0] . ' C' . $position['from'][1];
81 if ( isset( $position['to'] ) )
82 $str .= ' -> L' . $position['to'][0] . ' C' . $position['to'][1];
83 $str .= ':';
84 }
85 $str .= $text;
86 if ( class_exists( 'ezcli' ) )
87 {
88 $cli = eZCLI::instance();
89 $cli->warning( $str );
90 }
91 else
92 {
93 eZDebug::writeWarning( $str, __METHOD__ );
94 }
95 }
96
100 function isTranformationLoaded( $name )
101 {
102 return in_array( $name, $this->TransformationFiles );
103 }
104
113 function loadTransformationFiles( $currentCharset, $transformationGroup )
114 {
115 $ini = eZINI::instance( 'transform.ini' );
116 $repositoryList = array( $ini->variable( 'Transformation', 'Repository' ) );
117 $files = $ini->variable( 'Transformation', 'Files' );
118 $extensions = $ini->variable( 'Transformation', 'Extensions' );
119 $repositoryList = array_merge( $repositoryList,
120 eZExtension::expandedPathList( $extensions, 'transformations' ) );
121
122 // Check if the current charset maps to a unicode group
123 // If it does it can trigger loading of additional files
124 $unicodeGroups = array();
125 $charsets = $ini->variable( 'Transformation', 'Charsets' );
126 foreach ( $charsets as $entry )
127 {
128 list ( $charset, $group ) = explode( ';', $entry, 2 );
129 $charset = eZCharsetInfo::realCharsetCode( $charset );
130 if ( $charset == $currentCharset )
131 {
132 if ( !in_array( $group, $unicodeGroups ) )
133 $unicodeGroups[] = $group;
134 }
135 }
136
137 // If we are using transformation groups then add that as
138 // a unicode group. This causes it load transformation files
139 // specific to that group.
140 if ( $transformationGroup !== false )
141 $unicodeGroups[] = $transformationGroup;
142
143 // Add any extra files from the unicode groups
144 foreach ( $unicodeGroups as $unicodeGroup )
145 {
146 if ( $ini->hasGroup( $unicodeGroup ) )
147 {
148 $files = array_merge( $files, $ini->variable( $unicodeGroup, 'Files' ) );
149 $extensions = $ini->variable( $unicodeGroup, 'Extensions' );
150 $repositoryList = array_merge( $repositoryList,
151 eZExtension::expandedPathList( $extensions, 'transformations' ) );
152 }
153 }
154
155 foreach ( $files as $file )
156 {
157 // Only load files that are not currently loaded
158 if ( $this->isTranformationLoaded( $file ) )
159 continue;
160
161 foreach ( $repositoryList as $repository )
162 {
163 $trFile = $repository . '/' . $file;
164 if ( file_exists( $trFile ) )
165 {
166 $this->parseTransformationFile( $trFile, $file );
167 }
168 }
169 }
170 }
171
177 function parseTransformationFile( $filename, $name )
178 {
179 // eZDebug::writeDebug( "Parsing file $filename" );
180 $tbl = array();
181
182 $fd = fopen( $filename, "rb" );
183 if ( !$fd )
184 {
185 $this->error( "Failed opening $filename" );
186 return false;
187 }
188
189 $this->TransformationFiles[] = $name;
190
191 $this->ISOUnicodeCodec = eZTextCodec::instance( 'iso-8859-1', 'unicode' );
192
193 $buffer = '';
194 $lineNum = 1;
195 $i = 0;
196 $hexValues = "0123456789abcdefABCDEF";
197 $identifier = false;
198
199 // The big funky parser starts here
200 // It starts by reading a chunk of data from the file
201 // then splits everything into an array with lines.
202 // Then it traverses one line at a time looking for
203 // identifiers and rules. Comments will be removed before the
204 // line is parsed for identifiers and rules.
205
206 while ( !feof( $fd ) or strlen( $buffer ) > 0 )
207 {
208 $lines = array();
209 $len = strlen( $buffer );
210 // Check if we have data in the buffer yet
211 // Note: The actual buffer reading is done at the end of this while loop
212 if ( $len > 0 )
213 {
214 $endPos = false;
215 $eolPos = 0;
216 // Look for complete lines and append to $lines
217 while ( $eolPos !== false and $eolPos < $len )
218 {
219 $eolPos = strpos( $buffer, "\n", $endPos );
220 if ( $eolPos !== false )
221 {
222 $line = substr( $buffer, $endPos, $eolPos - $endPos );
223 $lines[] = array( 'text' => $line,
224 'line' => $lineNum );
225 ++$lineNum;
226 $endPos = $eolPos + 1;
227 }
228 }
229
230 // If we have leftover data place that back in $buffer
231 if ( $endPos !== false )
232 {
233 $buffer = substr( $buffer, $endPos );
234 }
235 }
236
237 // Once we have some lines start parsing them one at a time
238 foreach ( $lines as $lineData )
239 {
240 $line = $lineData['text'];
241 $lineOrg = $line;
242 $linePos = $lineData['line'];
243 $commentPos = strpos( $line, '#' );
244 $origLine = $line;
245 // Get rid of any comments before we check the line
246 if ( $commentPos !== false )
247 {
248 $line = substr( $line, 0, $commentPos );
249 }
250 $trimLine = trim( $line );
251 // Skip empty lines
252 if ( strlen( $trimLine ) == 0 )
253 continue;
254
255 // print( "Line: '$line'\n" );
256
257 $unicodeData = false;
258
259 $sourceValue = false;
260 $sourceEndValue = false;
261 $destinationValues = false;
262 $transposeValue = false;
263 $transposeAdd = true;
264 $moduloValue = 1;
265 // source, marker, range_input, range_marker, map_input, transpose_input, replace_input
266 $state = 'source';
267 // map, transpose, replace
268 $type = false;
269
270 $len = strlen( $line );
271 if ( preg_match( '#^(.+):[ \t]*$#', $line, $matches ) )
272 {
273 $identifier = $matches[1];
274 if ( !preg_match( '#^[a-zA-Z_-][a-zA-Z0-9_-]*$#', $identifier ) )
275 {
276 $this->warning( "Invalid identifier '$identifier', can only contain a-z, a-Z - and _",
277 array( 'file' => $filename, 'from' => array( $linePos, strlen( $identifier ) ) ) );
278 $identifier = false;
279 continue;
280 }
281 // print( "identifier '$identifier'\n" );
282 continue;
283 }
284 else if ( $identifier === false )
285 {
286 $this->warning( "No identifier defined yet, skipping: '" . $line . "'",
287 array( 'file' => $filename, 'from' => array( $linePos, 0 ) ) );
288 continue;
289 }
290 else
291 {
292 $pos = 0;
293 $col = 0;
294 $failed = false;
295 while ( $pos < $len )
296 {
297 while ( $pos < $len and
298 ( $line[$pos] == ' ' or
299 $line[$pos] == "\t" ) )
300 {
301 ++$pos;
302 }
303 if ( $pos >= $len )
304 break;
305
306 $char = $line[$pos];
307 $unicodeData = false;
308 if ( $char == '"' )
309 {
310 $delimiterPos = $pos;
311 while ( $delimiterPos < $len )
312 {
313 $delimiterPos = strpos( $line, '"', $delimiterPos + 1 );
314 if ( $delimiterPos === false or
315 $delimiterPos <= $pos + 1 or
316 $line[$delimiterPos - 1] != "\\" )
317 break;
318 }
319 if ( $delimiterPos === false )
320 {
321 $this->warning( "No end-quote found for line, skipping: '$line'",
322 array( 'file' => $filename,
323 'from' => array( $linePos, $pos ),
324 'to' => array( $linePos, strlen( $line ) ) ) );
325 $pos = $len;
326 $failed = true;
327 break;
328 }
329 $str = str_replace( array( "\\\"", "\\\\" ),
330 array( "\"", "\\" ),
331 substr( $line, $pos + 1, $delimiterPos - $pos - 1 ) );
332 // print( "string '$str'\n" );
333 $pos = $delimiterPos + 1;
334 $unicodeData = array( 'value' => $str,
335 'type' => 'string' );
336 }
337 else if ( $char == 'U' and
338 $pos + 1 < $len and
339 $line[$pos + 1] == '+' )
340 {
341 $hexPos = $pos + 2;
342 if ( $hexPos + 4 > $len )
343 {
344 $col = $hexPos;
345 $this->warning( "Found U+ value with " . ( 4 - ( $len - $hexPos ) ) . " missing hex numbers",
346 array( 'file' => $filename,
347 'from' => array( $linePos, $hexPos ) ) );
348 $failed = true;
349 $pos = $hexPos;
350 break;
351 }
352 $hasHexValues = true;
353 for ( $offset = 0; $offset < 4; ++$offset )
354 {
355 $hexChar = $line[$hexPos + $offset];
356 if ( $hexChar == ' ' or
357 $hexChar == "\t" )
358 {
359 $col = $hexPos + $offset;
360 $hasHexValues = false;
361 $this->warning( "Found U+ value with " . ( 4 - $offset ) . " missing hex numbers",
362 array( 'file' => $filename,
363 'from' => array( $linePos, $hexPos ),
364 'to' => array( $linePos, $hexPos + $offset ) ) );
365 $failed = true;
366 $pos = $hexPos + $offset;
367 break;
368 }
369 if ( strpos( $hexValues, $hexChar ) === false )
370 {
371 $col = $hexPos + $offset;
372 $hasHexValues = false;
373 $this->warning( "Found U+ value with invalid hex numbers ($hexChar)",
374 array( 'file' => $filename,
375 'from' => array( $linePos, $hexPos ),
376 'to' => array( $linePos, $hexPos + $offset ) ) );
377 $pos = $hexPos + $offset;
378 $failed = true;
379 break;
380 }
381 }
382 if ( $failed )
383 break;
384 if ( $hasHexValues )
385 {
386 $unicodeValue = hexdec( substr( $line, $hexPos, 4 ) );
387 $unicodeData = array( 'value' => $unicodeValue,
388 'type' => 'unicode' );
389 // print( "unicode U+ '$unicodeValue'\n" );
390 }
391 $pos = $hexPos + 4;
392 }
393 else if ( strpos( $hexValues, $char ) !== false and
394 $pos + 1 < $len and
395 strpos( $hexValues, $line[$pos + 1] ) !== false )
396 {
397 $hexPos = $pos;
398 if ( $hexPos + 2 > $len )
399 {
400 $col = $len;
401 $this->warning( "Found ASCII value with " . ( 2 - ( $len - $hexPos ) ) . " missing hex numbers",
402 array( 'file' => $filename,
403 'from' => array( $linePos, $hexPos ) ) );
404 $pos = $hexPos;
405 $failed = true;
406 break;
407 }
408 $hasHexValues = true;
409 for ( $offset = 0; $offset < 2; ++$offset )
410 {
411 $hexChar = $line[$hexPos + $offset];
412 if ( $hexChar == ' ' or
413 $hexChar == "\t" )
414 {
415 $col = $hexPos + $offset;
416 $hasHexValues = false;
417 $this->warning( "Found ASCII value with " . ( 2 - $offset ) . " missing hex numbers",
418 array( 'file' => $filename,
419 'from' => array( $linePos, $hexPos ),
420 'to' => array( $linePos, $hexPos + $offset ) ) );
421 $pos = $hexPos + $offset;
422 $failed = true;
423 break;
424 }
425 if ( strpos( $hexValues, $hexChar ) === false )
426 {
427 $col = $hexPos + $offset;
428 $hasHexValues = false;
429 $this->warning( "Found ASCII value with invalid hex numbers ($hexChar)",
430 array( 'file' => $filename,
431 'from' => array( $linePos, $hexPos ),
432 'to' => array( $linePos, $hexPos + $offset ) ) );
433 $pos = $hexPos + $offset;
434 $failed = true;
435 break;
436 }
437 }
438 if ( $failed )
439 break;
440 if ( $hasHexValues )
441 {
442 $asciiValue = hexdec( substr( $line, $hexPos, 4 ) );
443 // print( "unicode ASCII '$asciiValue'\n" );
444 $unicodeData = array( 'value' => $asciiValue,
445 'type' => 'ascii' );
446 }
447 $pos = $hexPos + 2;
448 }
449 else if ( substr( $line, $pos, 6 ) == 'remove' )
450 {
451 // print( "remove character\n" );
452 $unicodeData = array( 'value' => false,
453 'type' => 'remove' );
454 $pos += 6;
455 }
456 else if ( substr( $line, $pos, 4 ) == 'keep' )
457 {
458 // print( "keep character\n" );
459 $unicodeData = array( 'value' => true,
460 'type' => 'keep' );
461 $pos += 4;
462 }
463
464 if ( $unicodeData )
465 {
466 // print( "data state: $state\n" );
467 // source, marker, range_input, range_marker, map_input, transpose_input, replace_input, transpose_modulo
468 if ( $state == 'source' )
469 {
470 if ( $unicodeData['type'] == 'string' and
471 strlen( $unicodeData['value'] ) > 1 )
472 {
473 $this->warning( "Text string with more than one character cannot be used as input value '" . $unicodeData['value'] . "'",
474 array( 'file' => $filename,
475 'from' => array( $linePos, $pos ) ) );
476 $failed = true;
477 break;
478 }
479 $sourceValue = $this->extractUnicodeValue( $unicodeData );
480 $state = 'marker';
481 }
482 else if ( $state == 'marker' )
483 {
484 $this->warning( "Source value not expected, a source value has already been extracted at $line" . "[$pos]",
485 array( 'file' => $filename,
486 'from' => array( $linePos, $pos ) ) );
487 $failed = true;
488 break;
489 }
490 else if ( $state == 'range_input' )
491 {
492 if ( $unicodeData['type'] == 'string' and
493 strlen( $unicodeData['value'] ) > 1 )
494 {
495 $this->warning( "Text string with more than one character cannot be used as range end value '" . $unicodeData['value'] . "'",
496 array( 'file' => $filename,
497 'from' => array( $linePos, $pos ) ) );
498 $failed = true;
499 break;
500 }
501 $sourceEndValue = $this->extractUnicodeValue( $unicodeData );
502 $state = 'range_marker_or_modulo';
503 }
504 else if ( $state == 'range_marker_or_modulo' or
505 $state == 'range_marker' )
506 {
507 $this->warning( "Range value not expected, a range value has already been extracted at $line" . "[$pos]",
508 array( 'file' => $filename,
509 'from' => array( $linePos, $pos ) ) );
510 $failed = true;
511 break;
512 }
513 else if ( $state == 'map_input' )
514 {
515 if ( !is_array( $destinationValues ) )
516 $destinationValues = array();
517 $destinationValues = array_merge( $destinationValues,
518 $this->extractUnicodeValues( $unicodeData ) );
519 $type = 'map';
520 }
521 else if ( $state == 'replace_input' )
522 {
523 if ( !is_array( $destinationValues ) )
524 $destinationValues = array();
525 $destinationValues = array_merge( $destinationValues,
526 $this->extractUnicodeValues( $unicodeData ) );
527 $type = 'replace';
528 }
529 else if ( $state == 'transpose_input' )
530 {
531 if ( $unicodeData['type'] == 'string' and
532 strlen( $unicodeData['value'] ) > 1 )
533 {
534 $this->warning( "Text string with more than one character cannot be used as transpose value '" . $unicodeData['value'] . "'",
535 array( 'file' => $filename,
536 'from' => array( $linePos, $pos ) ) );
537 $failed = true;
538 break;
539 }
540 $transposeValue = $this->extractUnicodeValue( $unicodeData );
541 $type = 'transpose';
542 }
543 else if ( $state == 'transpose_modulo' )
544 {
545 if ( $unicodeData['type'] == 'string' and
546 strlen( $unicodeData['value'] ) > 1 )
547 {
548 $this->warning( "Text string with more than one character cannot be used as transpose modulo value '" . $unicodeData['value'] . "'",
549 array( 'file' => $filename,
550 'from' => array( $linePos, $pos ) ) );
551 $failed = true;
552 break;
553 }
554 $moduloValue = $this->extractUnicodeValue( $unicodeData );
555 if ( $moduloValue == 0 )
556 {
557 $this->error( "Modulo value of 0 is not allowed, 1 will be used instead",
558 array( 'file' => $filename,
559 'from' => array( $linePos, $pos ) ) );
560 // Note: There is another 0 check in generateSimpleMappingTable()
561 }
562 // print( "modulo value=$moduloValue\n" );
563 $state = 'range_marker';
564 }
565 }
566 else if ( !$failed )
567 {
568 // print( "command state: $state\n" );
569 // source, marker, range_input, range_marker, map_input, transpose_input, replace_input
570 if ( $state == 'source' )
571 {
572 if ( $char == '=' )
573 {
574 $this->warning( "Cannot use map marker $char without prior character value",
575 array( 'file' => $filename,
576 'from' => array( $linePos, $pos ) ) );
577 $failed = true;
578 break;
579 }
580 else if ( $char == '+' or
581 $char == '-' )
582 {
583 $this->warning( "Cannot use range marker $char without prior character value",
584 array( 'file' => $filename,
585 'from' => array( $linePos, $pos ) ) );
586 $failed = true;
587 break;
588 }
589 else
590 {
591 $this->warning( "Unknown character '$char', expecting input value",
592 array( 'file' => $filename,
593 'from' => array( $linePos, $pos ) ) );
594 $failed = true;
595 break;
596 }
597 }
598 else if ( $state == 'marker' )
599 {
600 if ( $char == '=' )
601 {
602 $state = 'map_input';
603 ++$pos;
604 }
605 else if ( $char == '-' )
606 {
607 $state = 'range_input';
608 ++$pos;
609 }
610 else if ( $char == '+' )
611 {
612 $this->warning( "Cannot use range marker $char without prior character value",
613 array( 'file' => $filename,
614 'from' => array( $linePos, $pos ) ) );
615 $failed = true;
616 break;
617 }
618 else
619 {
620 $this->warning( "Unknown character '$char', expecting marker",
621 array( 'file' => $filename,
622 'from' => array( $linePos, $pos ) ) );
623 $failed = true;
624 break;
625 }
626 }
627 else if ( $state == 'range_marker_or_modulo' or
628 $state == 'range_marker' )
629 {
630 if ( $state == 'range_marker_or_modulo' and
631 $char == '%' )
632 {
633 // print( "found modulo marker\n" );
634 // Look for modulo value
635 $state = 'transpose_modulo';
636 ++$pos;
637 }
638 else if ( $char == '=' )
639 {
640 $state = 'replace_input';
641 ++$pos;
642 }
643 else if ( $char == '-' or
644 $char == '+' )
645 {
646 $transposeAdd = ( $char == '+' ? true : false );
647 $state = 'transpose_input';
648 ++$pos;
649 }
650 else
651 {
652 $this->warning( "Unknown character '$char', expecting range end value",
653 array( 'file' => $filename,
654 'from' => array( $linePos, $pos ) ) );
655 $failed = true;
656 break;
657 }
658 }
659 else if ( $state == 'map_input' )
660 {
661 if ( $char == '=' )
662 {
663 $this->warning( "Duplicate mapping marker $char",
664 array( 'file' => $filename,
665 'from' => array( $linePos, $pos ) ) );
666 $failed = true;
667 break;
668 }
669 else if ( $char == '-' or
670 $char == '+' )
671 {
672 $this->warning( "Already mapping values, cannot use range/transpose marker $char",
673 array( 'file' => $filename,
674 'from' => array( $linePos, $pos ) ) );
675 $failed = true;
676 break;
677 }
678 else
679 {
680 $this->warning( "Unknown character '$char', expecting output values",
681 array( 'file' => $filename,
682 'from' => array( $linePos, $pos ) ) );
683 $failed = true;
684 break;
685 }
686 }
687 else if ( $state == 'transpose_modulo' )
688 {
689 if ( $char == '%' )
690 {
691 $this->warning( "Modulo marker already used, cannot use $char",
692 array( 'file' => $filename,
693 'from' => array( $linePos, $pos ) ) );
694 $failed = true;
695 break;
696 }
697 else if ( $char == '-' or
698 $char == '+' )
699 {
700 $this->warning( "Transpose marker $char used, but no modulo value has been found yet",
701 array( 'file' => $filename,
702 'from' => array( $linePos, $pos ) ) );
703 $failed = true;
704 break;
705 }
706 else
707 {
708 $this->warning( "Unknown character '$char', expecting modulo value",
709 array( 'file' => $filename,
710 'from' => array( $linePos, $pos ) ) );
711 $failed = true;
712 break;
713 }
714 }
715 else if ( $state == 'transpose_input' )
716 {
717 if ( $char == '=' )
718 {
719 $this->warning( "Already transposing, cannot use mapping marker $char",
720 array( 'file' => $filename,
721 'from' => array( $linePos, $pos ) ) );
722 $failed = true;
723 break;
724 }
725 else if ( $char == '-' or
726 $char == '+' )
727 {
728 $this->warning( "Duplicate transpose marker $char",
729 array( 'file' => $filename,
730 'from' => array( $linePos, $pos ) ) );
731 $failed = true;
732 break;
733 }
734 else
735 {
736 $this->warning( "Unknown character '$char', expecting transpose value",
737 array( 'file' => $filename,
738 'from' => array( $linePos, $pos ) ) );
739 $failed = true;
740 break;
741 }
742 }
743 else if ( $state == 'replace_input' )
744 {
745 if ( $char == '=' )
746 {
747 $this->warning( "Already replacing, cannot use mapping marker $char",
748 array( 'file' => $filename,
749 'from' => array( $linePos, $pos ) ) );
750 $failed = true;
751 break;
752 }
753 else if ( $char == '-' or
754 $char == '+' )
755 {
756 $this->warning( "Already replacing, cannot use transpose marker $char",
757 array( 'file' => $filename,
758 'from' => array( $linePos, $pos ) ) );
759 $failed = true;
760 break;
761 }
762 else
763 {
764 $this->warning( "Unknown character '$char', expecting replace value",
765 array( 'file' => $filename,
766 'from' => array( $linePos, $pos ) ) );
767 $failed = true;
768 break;
769 }
770 }
771 }
772 }
773 if ( !$failed )
774 {
775 if ( $identifier )
776 {
777 // print( "\nGot type '$type'\n" );
778 // if ( is_array( $destinationValues ) )
779 // $destinationValues = array_diff( $destinationValues, array( '' ) );
780
781 if ( !isset( $tbl[$identifier] ) )
782 $tbl[$identifier] = array();
783
784 if ( $type == 'map' )
785 {
786 // print( "***mapping***:\n" . $sourceValue . ' => ' . implode( ', ', $destinationValues ) . "\n\n" );
787 $this->appendDirectMapping( $tbl[$identifier], $identifier, $sourceValue, $destinationValues );
788 }
789 else if ( $type == 'replace' )
790 {
791 // print( "***replacing***:\n" . $sourceValue . ' - ' . $sourceEndValue . ' => ' . implode( ', ', $destinationValues ) . "\n\n" );
792 $this->appendReplaceMapping( $tbl[$identifier], $identifier, $sourceValue, $sourceEndValue, $destinationValues );
793 }
794 else if ( $type == 'transpose' )
795 {
796 // print( "***transposing***:\n" . $sourceValue . ' - ' . $sourceEndValue . ' % ' . $moduloValue . ' + ' . $transposeValue . "\n\n" );
797 $this->appendTransposeMapping( $tbl[$identifier], $identifier, $sourceValue, $sourceEndValue, $transposeValue, $transposeAdd, $moduloValue );
798 }
799 }
800 // else
801 // {
802 // print( "No identifier found yet, skipping entry!!!!!!!!!!\n" );
803 // }
804 }
805 else
806 {
807 // $this->warning( "Failed adding mapper",
808 // array( 'file' => $filename,
809 // 'from' => array( $linePos, $pos ) ) );
810 }
811 }
812 }
813
814 // Here we read more data from the file, appending to
815 // the $buffer variable
816 if ( !feof( $fd ) )
817 {
818 $buffer .= fread( $fd, 4096 );
819
820 // Make sure we have Unix endline characters
821 $buffer = preg_replace( "#(\r\n|\r|\n)#", "\n", $buffer );
822 }
823 ++$i;
824 }
825
826 fclose( $fd );
827
828 $this->TransformationTables = array_merge( $this->TransformationTables, $tbl );
829 }
830
839 function appendDirectMapping( &$block, $identifier, $sourceValue, $destinationValues )
840 {
841 $count = count( $block );
842 if ( count( $destinationValues ) == 1 )
843 $destinationValues = array_pop( $destinationValues );
844 if ( isset( $block[$count - 1] ) and
845 $block[$count - 1][0] == self::TYPE_DIRECT and
846 $block[$count - 1][2] == $identifier )
847 {
848 $block[$count - 1][1][$sourceValue] = $destinationValues;
849 }
850 else
851 {
852 $block[] = array( self::TYPE_DIRECT,
853 array( $sourceValue => $destinationValues ),
854 $identifier );
855
856 }
857 }
858
868 function appendReplaceMapping( &$block, $identifier, $sourceValue, $sourceEndValue, $destinationValues )
869 {
870 $count = count( $block );
871 if ( count( $destinationValues ) == 1 )
872 $destinationValues = array_pop( $destinationValues );
873 if ( isset( $block[$count - 1] ) and
874 $block[$count - 1][0] == self::TYPE_REPLACE and
875 $block[$count - 1][2] == $identifier )
876 {
877 $block[$count - 1][1][] = array( $sourceValue, $sourceEndValue, $destinationValues );
878 }
879 else
880 {
881 $block[] = array( self::TYPE_REPLACE,
882 array( array( $sourceValue, $sourceEndValue, $destinationValues ) ),
883 $identifier );
884
885 }
886 }
887
898 function appendTransposeMapping( &$block, $identifier, $sourceValue, $sourceEndValue, $transposeValue, $addValue, $moduloValue )
899 {
900 $count = count( $block );
901 if ( isset( $block[$count - 1] ) and
902 $block[$count - 1][0] == self::TYPE_RANGE and
903 $block[$count - 1][2] == $identifier )
904 {
905 $block[$count - 1][1][] = array( $sourceValue, $sourceEndValue, $addValue ? $transposeValue : -$transposeValue, $moduloValue );
906 }
907 else
908 {
909 $block[] = array( self::TYPE_RANGE,
910 array( array( $sourceValue, $sourceEndValue, $addValue ? $transposeValue : -$transposeValue, $moduloValue ) ),
911 $identifier );
912
913 }
914 }
915
920 function extractUnicodeValue( $data )
921 {
922 $type = $data['type'];
923 if ( $type == 'string' )
924 {
925 $list = $this->ISOUnicodeCodec->convertString( $data['value'][0] );
926 return $list[0];
927 }
928 else if ( $type == 'ascii' )
929 {
930 return $data['value'];
931 }
932 else if ( $type == 'unicode' )
933 {
934 return $data['value'];
935 }
936 else if ( $type == 'remove' )
937 {
938 return false;
939 }
940 else if ( $type == 'keep' )
941 {
942 return true;
943 }
944 return null;
945 }
946
951 function extractUnicodeValues( $data )
952 {
953 $type = $data['type'];
954 if ( $type == 'string' )
955 {
956 return $this->ISOUnicodeCodec->convertString( $data['value'] );
957 }
958 else if ( $type == 'ascii' )
959 {
960 return array( $data['value'] );
961 }
962 else if ( $type == 'unicode' )
963 {
964 return array( $data['value'] );
965 }
966 else if ( $type == 'remove' )
967 {
968 return array( false );
969 }
970 else if ( $type == 'keep' )
971 {
972 return array( true );
973 }
974 return array();
975 }
976
983 function expandInheritance( $table )
984 {
985 $newTable = array();
986 foreach ( $table as $tableItem )
987 {
988 if ( is_string( $tableItem ) )
989 {
990 $identifier = $tableItem;
991 $subTable = $this->mappingTable( $identifier );
992 if ( !$subTable )
993 {
994 eZDebug::writeError( "Failed to fetch mapping table for identifier: '$identifier'" );
995 }
996 else
997 {
998 $subTable = $this->expandInheritance( $subTable );
999 $newTable = array_merge( $newTable, $subTable );
1000 }
1001 }
1002 else
1003 {
1004 $newTable[] = $tableItem;
1005 }
1006 }
1007 return $newTable;
1008 }
1009
1018 function ordinalValues( $table, $list )
1019 {
1020 $ordinals = array();
1021 if ( is_string( $list ) )
1022 {
1023 $len = strlen( $list );
1024 for ( $offset = 0; $offset < $len; ++$offset )
1025 {
1026 $ordinals[] = ord( $list[$offset] );
1027 }
1028 }
1029 else if ( is_numeric( $list ) )
1030 {
1031 $ordinals[] = $list;
1032 }
1033 else if ( is_array( $list ) )
1034 {
1035 foreach ( $list as $item )
1036 {
1037 $ordinals = array_merge( $ordinals, eZCodeMapper::ordinalValues( $table, $item ) );
1038 }
1039 }
1040 $ordinals = eZCodeMapper::mapOrdinals( $table, $ordinals );
1041 return $ordinals;
1042 }
1043
1049 function mapOrdinals( $table, $ordinals )
1050 {
1051 $mappedOrdinals = array();
1052 foreach ( $ordinals as $ordinal )
1053 {
1054 while ( !is_array( $ordinal ) and isset( $table[$ordinal] ) )
1055 {
1056 $ordinal = $table[$ordinal];
1057 if ( is_array( $ordinal ) )
1058 {
1059 $ordinal = eZCodeMapper::mapOrdinals( $table, $ordinal );
1060 }
1061 }
1062 if ( is_array( $ordinal ) )
1063 $mappedOrdinals = array_merge( $mappedOrdinals, $ordinal );
1064 else
1065 $mappedOrdinals[] = $ordinal;
1066 }
1067 return $mappedOrdinals;
1068 }
1069
1076 protected function mapExistingCodes( $unicodeMap, $fromCode, $toCode )
1077 {
1078 foreach ( $unicodeMap as $from => $to )
1079 {
1080 if ( is_array( $to ) )
1081 {
1082 $newTo = array();
1083 foreach ( $to as $ordinal )
1084 {
1085 if ( $ordinal == $fromCode )
1086 {
1087 $newTo = array_merge( $newTo, array( $toCode ) );
1088 }
1089 else
1090 {
1091 $newTo[] = $ordinal;
1092 }
1093 }
1094 $unicodeMap[$from] = $newTo;
1095 }
1096 else if ( $to == $fromCode )
1097 {
1098 $unicodeMap[$from] = $toCode;
1099 }
1100 }
1101 return $unicodeMap;
1102 }
1103
1113 function generateSimpleMappingTable( $table, $allowedRanges )
1114 {
1115 if ( !is_array( $table ) )
1116 return false;
1117 $unicodeMap = array();
1118 foreach ( $table as $tableItem )
1119 {
1120 $type = $tableItem[0];
1121 $item = $tableItem[1];
1122 if ( isset( $tableItem[2] ) )
1123 {
1124 $identifier = $tableItem[2];
1125 // print( "identifier: $identifier\n" );
1126 }
1127 if ( $type == self::TYPE_DIRECT )
1128 {
1129 foreach ( $item as $fromCode => $toCode )
1130 {
1131 // print( "from: $fromCode, to: $toCode\n" );
1132 // if ( $fromCode == 1026 )
1133 // {
1134 // print( "<pre>oldcode<br/>" ); var_dump( $toCode ); print( "</pre>" );
1135 // }
1136 $toCode = eZCodeMapper::ordinalValues( $unicodeMap, $toCode );
1137 // if ( $fromCode == 1026 )
1138 // {
1139 // print( "<pre>newcode<br/>" ); var_dump( $toCode ); print( "</pre>" );
1140 // }
1141 if ( count( $allowedRanges ) == 0 )
1142 {
1143 if ( count( $toCode ) == 1 )
1144 $toCode = $toCode[0];
1145 // If the mapping already exists we skip it
1146 if ( isset( $unicodeMap[$fromCode] ) )
1147 continue;
1148
1149 $unicodeMap[$fromCode] = $toCode;
1150 $unicodeMap = eZCodeMapper::mapExistingCodes( $unicodeMap, $fromCode, $toCode );
1151 }
1152 else
1153 {
1154 $allowed = false;
1155 foreach ( $allowedRanges as $allowedRange )
1156 {
1157 if ( $fromCode >= $allowedRange[0] and
1158 $fromCode <= $allowedRange[1] )
1159 {
1160 $allowed = true;
1161 break;
1162 }
1163 }
1164 if ( !$allowed )
1165 continue;
1166
1167 $toCodeList = $toCode;
1168 $newToCodeList = array();
1169 foreach ( $toCodeList as $toCode )
1170 {
1171 if ( is_bool( $toCode ) )
1172 {
1173 $newToCodeList[] = $toCode;
1174 continue;
1175 }
1176 foreach ( $allowedRanges as $allowedRange )
1177 {
1178 if ( $toCode >= $allowedRange[0] and
1179 $toCode <= $allowedRange[1] )
1180 {
1181 break;
1182 }
1183 }
1184 if ( $allowed )
1185 {
1186 $newToCodeList[] = $toCode;
1187 }
1188 }
1189 $toCode = $newToCodeList;
1190 if ( count( $toCode ) > 0 )
1191 {
1192 if ( count( $toCode ) == 1 )
1193 $toCode = $toCode[0];
1194
1195 // If the mapping already exists we skip it
1196 if ( isset( $unicodeMap[$fromCode] ) )
1197 continue;
1198
1199 $unicodeMap = eZCodeMapper::mapExistingCodes( $unicodeMap, $fromCode, $toCode );
1200
1201 $unicodeMap[$fromCode] = $toCode;
1202 }
1203 }
1204 }
1205 }
1206 else if ( $type == self::TYPE_RANGE )
1207 {
1208 foreach ( $item as $rangeItem )
1209 {
1210 $start = $rangeItem[0];
1211 $stop = $rangeItem[1];
1212 if ( $start > $stop )
1213 {
1214 $tmp = $stop;
1215 $stop = $start;
1216 $start = $tmp;
1217 }
1218 $add = $rangeItem[2];
1219 $modulo = $rangeItem[3];
1220 // Sanity-check, to avoid infinite loops
1221 if ( $modulo == 0 )
1222 $modulo = 1;
1223 for ( $i = $start; $i <= $stop; $i += $modulo )
1224 {
1225 if ( count( $allowedRanges ) == 0 )
1226 {
1227 $allowed = true;
1228 }
1229 else
1230 {
1231 $allowed = false;
1232 foreach ( $allowedRanges as $allowedRange )
1233 {
1234 if ( $i >= $allowedRange[0] and
1235 $i <= $allowedRange[1] )
1236 {
1237 $allowed = true;
1238 break;
1239 }
1240 }
1241 if ( !$allowed )
1242 continue;
1243 }
1244
1245 $replace = $i + $add;
1246 $replace = eZCodeMapper::ordinalValues( $unicodeMap, $replace );
1247 if ( count( $allowedRanges ) == 0 )
1248 {
1249 if ( count( $replace ) == 0 )
1250 $replace = false;
1251 else if ( count( $replace ) == 1 )
1252 $replace = $replace[0];
1253 $unicodeMap = eZCodeMapper::mapExistingCodes( $unicodeMap, $i, $replace );
1254
1255 // If the mapping already exists we skip it
1256 if ( isset( $unicodeMap[$i] ) )
1257 continue;
1258
1259 $unicodeMap[$i] = $replace;
1260 }
1261 else
1262 {
1263 $newReplace = array();
1264 foreach ( $allowedRanges as $allowedRange )
1265 {
1266 foreach ( $replace as $replaceOrdinal )
1267 {
1268 if ( $replaceOrdinal >= $allowedRange[0] and
1269 $replaceOrdinal <= $allowedRange[1] )
1270 {
1271 $newReplace[] = $replaceOrdinal;
1272 }
1273 }
1274 }
1275 if ( count( $newReplace ) == 0 )
1276 $replace = false;
1277 else if ( count( $newReplace ) == 1 )
1278 $replace = $newReplace[0];
1279 else
1280 $replace = $newReplace;
1281
1282 // If the mapping already exists we skip it
1283 if ( isset( $unicodeMap[$i] ) )
1284 continue;
1285
1286 $unicodeMap = eZCodeMapper::mapExistingCodes( $unicodeMap, $i, $replace );
1287 $unicodeMap[$i] = $replace;
1288 }
1289 }
1290 }
1291 }
1292 else if ( $type == self::TYPE_REPLACE )
1293 {
1294 foreach ( $item as $rangeItem )
1295 {
1296 $start = $rangeItem[0];
1297 $stop = $rangeItem[1];
1298 if ( $start > $stop )
1299 {
1300 $tmp = $stop;
1301 $stop = $start;
1302 $start = $tmp;
1303 }
1304 $replace = $rangeItem[2];
1305 $replace = eZCodeMapper::ordinalValues( $unicodeMap, $replace );
1306 if ( count( $allowedRanges ) == 0 )
1307 {
1308 if ( count( $replace ) == 0 )
1309 $replace = false;
1310 else if ( count( $replace ) == 1 )
1311 $replace = $replace[0];
1312 for ( $i = $start; $i <= $stop; ++$i )
1313 {
1314 // If the mapping already exists we skip it
1315 if ( isset( $unicodeMap[$i] ) )
1316 continue;
1317
1318 $unicodeMap = eZCodeMapper::mapExistingCodes( $unicodeMap, $i, $replace );
1319 $unicodeMap[$i] = $replace;
1320 }
1321 }
1322 else
1323 {
1324 $newReplace = array();
1325 foreach ( $allowedRanges as $allowedRange )
1326 {
1327 foreach ( $replace as $replaceOrdinal )
1328 {
1329 if ( $replaceOrdinal >= $allowedRange[0] and
1330 $replaceOrdinal <= $allowedRange[1] )
1331 {
1332 $newReplace[] = $replaceOrdinal;
1333 }
1334 }
1335 }
1336 if ( count( $newReplace ) == 0 )
1337 $replace = false;
1338 else if ( count( $newReplace ) == 1 )
1339 $replace = $newReplace[0];
1340 else
1341 $replace = $newReplace;
1342 for ( $i = $start; $i <= $stop; ++$i )
1343 {
1344 $allowed = false;
1345 foreach ( $allowedRanges as $allowedRange )
1346 {
1347 if ( $i >= $allowedRange[0] and
1348 $i <= $allowedRange[1] )
1349 {
1350 $allowed = true;
1351 break;
1352 }
1353 }
1354 if ( $allowed )
1355 {
1356 // If the mapping already exists we skip it
1357 if ( isset( $unicodeMap[$i] ) )
1358 continue;
1359
1360 $unicodeMap = eZCodeMapper::mapExistingCodes( $unicodeMap, $i, $replace );
1361 $unicodeMap[$i] = $replace;
1362 }
1363 }
1364 }
1365 }
1366 }
1367 }
1368 return $unicodeMap;
1369 }
1370
1378 function generateMappingCode( $identifier )
1379 {
1380 if ( !is_array( $identifier ) )
1381 $identifier = array( $identifier );
1382 $table = $this->expandInheritance( $identifier );
1383
1384 // We allow all characters for now
1385 $allowedRanges = array();
1386 $simpleTable = $this->generateSimpleMappingTable( $table, $allowedRanges );
1387 ksort( $simpleTable );
1388 return $simpleTable;
1389 }
1390
1397 function generateCharsetMappingTable( $unicodeTable, $charset )
1398 {
1399 $codec = eZTextCodec::instance( 'unicode', $charset );
1400 if ( !$codec )
1401 {
1402 eZDebug::writeError( "Failed to create textcodec for charset '$charset'" );
1403 return false;
1404 }
1405
1406 $charsetTable = array();
1407 foreach ( $unicodeTable as $match => $replacement )
1408 {
1409 $matchLocal = $codec->convertString( array( $match ) );
1410 if ( is_array( $replacement ) )
1411 {
1412 $replacementLocal = $codec->convertString( $replacement );
1413 }
1414 else
1415 {
1416 $replacementLocal = $codec->convertString( array( $replacement ) );
1417 }
1418 $charsetTable[$matchLocal] = $replacementLocal;
1419 }
1420
1421 // Make sure longer string entries are placed before the shorter ones
1422 // This is very important when working with utf8 which have
1423 // variable length for characters
1424 krsort( $charsetTable );
1425 return $charsetTable;
1426 }
1427
1434 function decodeCommand( $name, $parameters )
1435 {
1436 $names = $this->ruleNames();
1437 $rules = array();
1438 switch ( $name )
1439 {
1440 // Special code handlers
1441 case 'url_cleanup_iri':
1442 case 'url_cleanup':
1443 case 'url_cleanup_compat':
1444 case 'identifier_cleanup':
1445 {
1446 } break;
1447
1448 case 'normalize':
1449 case 'search_normalize':
1450 case 'decompose':
1451 case 'diacritical':
1452 case 'lowercase':
1453 case 'uppercase':
1454 case 'search_cleanup':
1455 {
1456 if ( count( $parameters ) == 0 )
1457 {
1458 // Include all normalize rules
1459 foreach ( $names as $rule )
1460 {
1461 if ( preg_match( '#_'. $name . '$#', $rule ) )
1462 $rules[] = $rule;
1463 }
1464 }
1465 else
1466 {
1467 foreach ( $parameters as $parameter )
1468 {
1469 $rule = $parameter . '_' . $name;
1470 if ( in_array( $rule, $names ) )
1471 $rules[] = $rule;
1472 }
1473 }
1474 } break;
1475
1476 case 'transform':
1477 case 'transliterate':
1478 {
1479 $dividers = array( 'transform' => '_to_',
1480 'transliterate' => '_transliterate_' );
1481 $divider = $dividers[$name];
1482 if ( count( $parameters ) == 0 )
1483 {
1484 // Include all transformation rules
1485 foreach ( $names as $rule )
1486 {
1487 if ( preg_match( '#^[a-zA-Z][a-zA-Z0-9-]+'. $divider . '[a-zA-Z][a-zA-Z0-9-]+$#', $rule ) )
1488 $rules[] = $rule;
1489 }
1490 }
1491 else if ( count( $parameters ) == 2 )
1492 {
1493 $rule = $parameters[0] . $divider . $parameters[1];
1494 if ( in_array( $rule, $names ) )
1495 $rules[] = $rule;
1496 }
1497 } break;
1498
1499 default:
1500 {
1501 $ini = eZINI::instance( 'transform.ini' );
1502 $commands = $ini->variable( 'Extensions', 'Commands' );
1503 if ( isset( $commands[$name] ) )
1504 {
1505 break;
1506 }
1507 eZDebug::writeError( "Unknown command '$name'", __METHOD__ );
1508 } break;
1509 }
1510 return $rules;
1511 }
1512
1519 function generateCommandCode( $command, $charsetName )
1520 {
1521 if ( $command['command'] == 'url_cleanup_iri' )
1522 {
1523 $charsetNameTxt = var_export( $charsetName, true );
1524 $code = "\$text = eZCharTransform::commandUrlCleanupIRI( \$text, $charsetNameTxt );\n";
1525 return $code;
1526 }
1527 else if ( $command['command'] == 'url_cleanup' )
1528 {
1529 $charsetNameTxt = var_export( $charsetName, true );
1530 $code = "\$text = eZCharTransform::commandUrlCleanup( \$text, $charsetNameTxt );\n";
1531 return $code;
1532 }
1533 else if ( $command['command'] == 'url_cleanup_compat' )
1534 {
1535 $charsetNameTxt = var_export( $charsetName, true );
1536 $code = "\$text = eZCharTransform::commandUrlCleanupCompat( \$text, $charsetNameTxt );\n";
1537 return $code;
1538 }
1539 else if ( $command['command'] == 'identifier_cleanup' )
1540 {
1541 $code = ( "\$text = strtolower( \$text );\n" .
1542 "\$text = preg_replace( array( \"#[^a-z0-9_ ]#\",\n" .
1543 " \"/ /\",\n" .
1544 " \"/__+/\",\n" .
1545 " \"/^_|_$/\" ),\n" .
1546 " array( \" \",\n" .
1547 " \"_\",\n" .
1548 " \"_\",\n" .
1549 " \"\" ),\n" .
1550 " \$text );\n" );
1551 return $code;
1552 }
1553 else if ( $command['command'] == 'search_cleanup' )
1554 {
1555 $code = '';
1556 $nonCJKCharsets = $this->nonCJKCharsets();
1557 if ( !in_array( $charsetName, $nonCJKCharsets ) )
1558 {
1559 $code .= ( '// add N-Gram(N=2) chinese / japanese / korean multibyte characters' . "\n" .
1560 '$codec = eZTextCodec::instance( false, \'unicode\' );' . "\n" .
1561 "\n" .
1562 '$unicodeValueArray = $codec->convertString( $text );' . "\n" .
1563 "\n" .
1564 '$normalizedTextArray = array();' . "\n" .
1565 '$bFlag = false;' . "\n" .
1566 'foreach ( array_keys( $unicodeValueArray ) as $valueKey )' . "\n" .
1567 '{' . "\n" .
1568 ' // Check for word characters that should be broken up for search' . "\n" .
1569 ' if ( ( $unicodeValueArray[$valueKey] >= 12289 and' . "\n" .
1570 ' $unicodeValueArray[$valueKey] <= 12542 ) or' . "\n" .
1571 ' ( $unicodeValueArray[$valueKey] >= 13312 and' . "\n" .
1572 ' $unicodeValueArray[$valueKey] <= 40863 ) or' . "\n" .
1573 ' ( $unicodeValueArray[$valueKey] >= 44032 and' . "\n" .
1574 ' $unicodeValueArray[$valueKey] <= 55203 ) )' . "\n" .
1575 ' {' . "\n" .
1576 ' if ( $bFlag )' . "\n" .
1577 ' {' . "\n" .
1578 ' $normalizedTextArray[] = $unicodeValueArray[$valueKey];' . "\n" .
1579 ' }' . "\n" .
1580 ' $normalizedTextArray[] = 32; // A space' . "\n" .
1581 ' $normalizedTextArray[] = $unicodeValueArray[$valueKey];' . "\n" .
1582 ' $bFlag = true;' . "\n" .
1583 ' }' . "\n" .
1584 ' else' . "\n" .
1585 ' {' . "\n" .
1586 ' if ( $bFlag )' . "\n" .
1587 ' {' . "\n" .
1588 ' $normalizedTextArray[] = 32; // A space' . "\n" .
1589 ' }' . "\n" .
1590 ' $normalizedTextArray[] = $unicodeValueArray[$valueKey];' . "\n" .
1591 ' $bFlag = false;' . "\n" .
1592 ' }' . "\n" .
1593 '}' . "\n" .
1594 'if ( $bFlag )' . "\n" .
1595 '{' . "\n" .
1596 ' $normalizedTextArray[count($normalizedTextArray)-1]=32;' . "\n" .
1597 '}' . "\n" .
1598 '$revCodec = eZTextCodec::instance( \'unicode\', false ); // false means use internal charset' . "\n" .
1599 '$text = $revCodec->convertString( $normalizedTextArray );' . "\n" );
1600 }
1601 $code .= ( '$text = preg_replace( array( "#(\.){2,}#",' . "\n" .
1602 ' "#^\.#",' . "\n" .
1603 ' "#\s\.#",' . "\n" .
1604 ' "#\.\s#",' . "\n" .
1605 ' "#\.$#",' . "\n" .
1606 ' "#([^0-9])%#" ),' . "\n" .
1607 ' array( " ",' . "\n" .
1608 ' " ",' . "\n" .
1609 ' " ",' . "\n" .
1610 ' " ",' . "\n" .
1611 ' " ",' . "\n" .
1612 ' " " ),' . "\n" .
1613 ' $text );' . "\n" .
1614 '$ini = eZINI::instance();' . "\n" .
1615 'if ( $ini->variable( \'SearchSettings\', \'EnableWildcard\' ) != \'true\' )' . "\n" .
1616 '{' . "\n" .
1617 ' $text = str_replace( "*", " ", $text );' . "\n" .
1618 '}' . "\n" .
1619 '$charset = eZTextCodec::internalCharset();' . "\n" .
1620 '$hasUTF8 = ( $charset == "utf-8" );' . "\n" .
1621 "\n" .
1622 'if ( $hasUTF8 )' . "\n" .
1623 '{' . "\n" .
1624 ' $text = preg_replace( "#(\s+)#u", " ", $text );' . "\n" .
1625 '}' . "\n" .
1626 'else' . "\n" .
1627 '{' . "\n" .
1628 ' $text = preg_replace( "#(\s+)#", " ", $text );' . "\n" .
1629 '}' );
1630
1631 return $code;
1632 }
1633 else
1634 {
1635 $ini = eZINI::instance( 'transform.ini' );
1636 $commands = $ini->variable( 'Extensions', 'Commands' );
1637 if ( isset( $commands[$command['command']] ) )
1638 {
1639 list( $path, $className ) = explode( ':', $commands[$command['command']], 2 );
1640 if ( file_exists( $path ) )
1641 {
1642 $charsetNameTxt = var_export( $charsetName, true );
1643 $commandTxt = var_export( $command['command'], true );
1644 $pathTxt = var_export( $path, true );
1645 $code = "include_once( $pathTxt );\n\$text = $className::executeCommand( \$text, $commandTxt, $charsetNameTxt );\n";
1646 return $code;
1647 }
1648 else
1649 {
1650 eZDebug::writeError( "Could not locate include file '$path' for transformation '" . $command['command'] . "'" );
1651 }
1652 }
1653 }
1654 return false;
1655 }
1656
1663 function executeCommandCode( &$text, $command, $charsetName )
1664 {
1665 if ( $command['command'] == 'url_cleanup_iri' )
1666 {
1667 $text = eZCharTransform::commandUrlCleanupIRI( $text, $charsetName );
1668 return true;
1669 }
1670 else if ( $command['command'] == 'url_cleanup' )
1671 {
1672 $text = eZCharTransform::commandUrlCleanup( $text, $charsetName );
1673 return true;
1674 }
1675 else if ( $command['command'] == 'url_cleanup_compat' )
1676 {
1677 $text = eZCharTransform::commandUrlCleanupCompat( $text, $charsetName );
1678 return true;
1679 }
1680 else if ( $command['command'] == 'identifier_cleanup' )
1681 {
1682 $text = strtolower( $text );
1683 $text = preg_replace( array( "#[^a-z0-9_ ]#",
1684 "/ /",
1685 "/__+/",
1686 "/^_|_$/" ),
1687 array( " ",
1688 "_",
1689 "_",
1690 "" ),
1691 $text );
1692 return true;
1693 }
1694 else if ( $command['command'] == 'search_cleanup' )
1695 {
1696 $nonCJKCharsets = $this->nonCJKCharsets();
1697 if ( !in_array( $charsetName, $nonCJKCharsets ) )
1698 {
1699 // 4 Add spaces after chinese / japanese / korean multibyte characters
1700 $codec = eZTextCodec::instance( false, 'unicode' );
1701
1702 $unicodeValueArray = $codec->convertString( $text );
1703
1704 $normalizedTextArray = array();
1705 $bFlag = false;
1706 foreach ( array_keys( $unicodeValueArray ) as $valueKey )
1707 {
1708 // Check for word characters that should be broken up for search
1709 if ( ( $unicodeValueArray[$valueKey] >= 12289 and
1710 $unicodeValueArray[$valueKey] <= 12542 ) or
1711 ( $unicodeValueArray[$valueKey] >= 13312 and
1712 $unicodeValueArray[$valueKey] <= 40863 ) or
1713 ( $unicodeValueArray[$valueKey] >= 44032 and
1714 $unicodeValueArray[$valueKey] <= 55203 ) )
1715 {
1716 if ( $bFlag )
1717 {
1718 $normalizedTextArray[] = $unicodeValueArray[$valueKey];
1719 }
1720 $normalizedTextArray[] = 32; // A space
1721 $normalizedTextArray[] = $unicodeValueArray[$valueKey];
1722 $bFlag = true;
1723 }
1724 else
1725 {
1726 if ( $bFlag )
1727 {
1728 $normalizedTextArray[] = 32; // A space
1729 }
1730 $normalizedTextArray[] = $unicodeValueArray[$valueKey];
1731 $bFlag = false;
1732 }
1733 }
1734
1735 if ( $bFlag )
1736 {
1737 $normalizedTextArray[ count( $normalizedTextArray ) - 1 ] = 32;
1738 }
1739
1740 $revCodec = eZTextCodec::instance( 'unicode', false ); // false means use internal charset
1741 $text = $revCodec->convertString( $normalizedTextArray );
1742 }
1743
1744 // Make sure dots inside words/numbers are kept, the rest is turned into space
1745 $text = preg_replace( array( "#(\.){2,}#",
1746 "#^\.#",
1747 "#\s\.#",
1748 "#\.\s#",
1749 "#\.$#",
1750 "#([^0-9])%#" ), // Keep only % after a number
1751 array( " ",
1752 " ",
1753 " ",
1754 " ",
1755 " ",
1756 "$1 " ),
1757 $text );
1758 $ini = eZINI::instance();
1759 if ( $ini->variable( 'SearchSettings', 'EnableWildcard' ) != 'true' )
1760 {
1761 $text = str_replace( "*", " ", $text );
1762 }
1763 $charset = eZTextCodec::internalCharset();
1764 $hasUTF8 = ( $charset == "utf-8" );
1765
1766 if ( $hasUTF8 )
1767 {
1768 $text = preg_replace( "#(\s+)#u", " ", $text );
1769 }
1770 else
1771 {
1772 $text = preg_replace( "#(\s+)#", " ", $text );
1773 }
1774
1775 return true;
1776 }
1777 else
1778 {
1779 $ini = eZINI::instance( 'transform.ini' );
1780 $commands = $ini->variable( 'Extensions', 'Commands' );
1781 if ( isset( $commands[$command['command']] ) )
1782 {
1783 list( $path, $className ) = explode( ':', $commands[$command['command']], 2 );
1784 if ( file_exists( $path ) )
1785 {
1786 include_once( $path );
1787 $text = call_user_func_array( array( $className, 'executeCommand' ),
1788 array( $text, $command['command'], $charsetName ) );
1789 return true;
1790 }
1791 else
1792 {
1793 eZDebug::writeError( "Could not locate include file '$path' for transformation '" . $command['command'] . "'" );
1794 }
1795 }
1796 }
1797 return false;
1798 }
1799
1803 function nonCJKCharsets()
1804 {
1805 return array( 'adobe-standard-encoding',
1806 'cp437', 'cp737', 'cp775', 'cp850', 'cp852', 'cp855', 'cp857',
1807 'cp860', 'cp861', 'cp862', 'cp863', 'cp864', 'cp865', 'cp866',
1808 'cp869', 'cp874',
1809 'dec-mcs', 'hp-roman8',
1810 'iso-8859-1', 'iso-8859-2', 'iso-8859-3', 'iso-8859-4', 'iso-8859-5',
1811 'iso-8859-6', 'iso-8859-7', 'iso-8859-8', 'iso-8859-9', 'iso-8859-10',
1812 'iso-8859-11', 'iso-8859-13', 'iso-8859-14', 'iso-8859-15',
1813 'koi8-r', 'koi8-u', 'macintosh', 'next', 'us-ascii',
1814 'windows-1250', 'windows-1251', 'windows-1252', 'windows-1253',
1815 'windows-1254', 'windows-1255', 'windows-1256', 'windows-1257',
1816 'windows-1258' );
1817 }
1818
1820 public $TransformationTables;
1821 public $TransformationFiles;
1822 public $ISOUnicodeCodec;
1823 }
1824
1825 ?>
$i
$i
Definition: admin/adlist.php:91
$group
$group
Definition: admin/articleedit.php:799
$files
$files
Definition: articlepreview.php:91
$tmp
$tmp
Definition: bugview.php:99
eZCharTransform\commandUrlCleanupCompat
static commandUrlCleanupCompat( $text, $charsetName)
Definition: ezchartransform.php:376
eZCharTransform\commandUrlCleanup
static commandUrlCleanup( $text, $charsetName)
Definition: ezchartransform.php:388
eZCharTransform\commandUrlCleanupIRI
static commandUrlCleanupIRI( $text, $charsetName)
Definition: ezchartransform.php:404
eZCharsetInfo\realCharsetCode
static realCharsetCode( $charsetCode)
Definition: ezcharsetinfo.php:187
eZCodeMapper
Handles mapping of character codes.
Definition: ezcodemapper.php:20
eZCodeMapper\extractUnicodeValues
extractUnicodeValues( $data)
Definition: ezcodemapper.php:951
eZCodeMapper\parseTransformationFile
parseTransformationFile( $filename, $name)
Definition: ezcodemapper.php:177
eZCodeMapper\TYPE_DIRECT
const TYPE_DIRECT
Definition: ezcodemapper.php:21
eZCodeMapper\appendReplaceMapping
appendReplaceMapping(&$block, $identifier, $sourceValue, $sourceEndValue, $destinationValues)
Definition: ezcodemapper.php:868
eZCodeMapper\TYPE_RANGE
const TYPE_RANGE
Definition: ezcodemapper.php:22
eZCodeMapper\generateCommandCode
generateCommandCode( $command, $charsetName)
Definition: ezcodemapper.php:1519
eZCodeMapper\ruleNames
ruleNames()
Definition: ezcodemapper.php:44
eZCodeMapper\mapExistingCodes
mapExistingCodes( $unicodeMap, $fromCode, $toCode)
Definition: ezcodemapper.php:1076
eZCodeMapper\generateSimpleMappingTable
generateSimpleMappingTable( $table, $allowedRanges)
Definition: ezcodemapper.php:1113
eZCodeMapper\$TransformationFiles
$TransformationFiles
Definition: ezcodemapper.php:1821
eZCodeMapper\executeCommandCode
executeCommandCode(&$text, $command, $charsetName)
Definition: ezcodemapper.php:1663
eZCodeMapper\$TransformationTables
$TransformationTables
Definition: ezcodemapper.php:1820
eZCodeMapper\ordinalValues
ordinalValues( $table, $list)
Definition: ezcodemapper.php:1018
eZCodeMapper\error
error( $text, $position=false)
Definition: ezcodemapper.php:52
eZCodeMapper\mapOrdinals
mapOrdinals( $table, $ordinals)
Definition: ezcodemapper.php:1049
eZCodeMapper\decodeCommand
decodeCommand( $name, $parameters)
Definition: ezcodemapper.php:1434
eZCodeMapper\__construct
__construct()
Definition: ezcodemapper.php:25
eZCodeMapper\nonCJKCharsets
nonCJKCharsets()
Definition: ezcodemapper.php:1803
eZCodeMapper\warning
warning( $text, $position=false)
Definition: ezcodemapper.php:76
eZCodeMapper\generateCharsetMappingTable
generateCharsetMappingTable( $unicodeTable, $charset)
Definition: ezcodemapper.php:1397
eZCodeMapper\mappingTable
mappingTable( $identifier)
Definition: ezcodemapper.php:34
eZCodeMapper\extractUnicodeValue
extractUnicodeValue( $data)
Definition: ezcodemapper.php:920
eZCodeMapper\generateMappingCode
generateMappingCode( $identifier)
Definition: ezcodemapper.php:1378
eZCodeMapper\appendDirectMapping
appendDirectMapping(&$block, $identifier, $sourceValue, $destinationValues)
Definition: ezcodemapper.php:839
eZCodeMapper\expandInheritance
expandInheritance( $table)
Definition: ezcodemapper.php:983
eZCodeMapper\loadTransformationFiles
loadTransformationFiles( $currentCharset, $transformationGroup)
Definition: ezcodemapper.php:113
eZCodeMapper\isTranformationLoaded
isTranformationLoaded( $name)
Definition: ezcodemapper.php:100
eZCodeMapper\TYPE_REPLACE
const TYPE_REPLACE
Definition: ezcodemapper.php:23
eZCodeMapper\appendTransposeMapping
appendTransposeMapping(&$block, $identifier, $sourceValue, $sourceEndValue, $transposeValue, $addValue, $moduloValue)
Definition: ezcodemapper.php:898
eZCodeMapper\$ISOUnicodeCodec
$ISOUnicodeCodec
Definition: ezcodemapper.php:1822
eZDebug\writeError
static writeError( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:546
eZDebug\writeWarning
static writeWarning( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:503
eZExtension\expandedPathList
static expandedPathList( $extensionList, $subdirectory=false)
Definition: ezextension.php:283
eZTextCodec\internalCharset
static internalCharset()
Definition: ezi18n/classes/eztextcodec.php:547
eZTextCodec\instance
static instance( $inputCharsetCode, $outputCharsetCode=false, $alwaysReturn=true)
Definition: ezi18n/classes/eztextcodec.php:447
$ini
$ini
Definition: classes/admin/linklist.php:64
$item
$item
Definition: classes/admin/linklist.php:228
$type
$type
Definition: classes/admin/linkselect.php:220
$name
$name
Definition: companytypelist.php:194
$lines
else $lines
Definition: csseditor.php:58
file_exists
static file_exists( $inifilename)
Definition: eZPBINIFile.php:195
$replace
$replace
Definition: export_froogle.php:140
$str
$str
Definition: ezarticle/modules/content.php:30
$file
$file
Definition: ezfilemanager/user/filedownload.php:35
$offset
$offset
Definition: ezstats/admin/cron.php:51
$count
$count
Definition: onlinetypelist.php:108
$position
$position
Definition: quizscores.php:85
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.