Exponential 6.0.13 Exponential Enterprise Open Source CMS - PHP Class Reference

ezurlwildcard.php
Go to the documentation of this file.
1 <?php
18 class eZURLWildcard extends eZPersistentObject
19 {
24 const WILDCARDS_PER_CACHE_FILE = 100;
25
30 const TYPE_NONE = 0;
31 const TYPE_FORWARD = 1;
32 const TYPE_DIRECT = 2;
33
38 const CACHE_SIGNATURE = 'urlalias-wildcard';
39
44 protected static $cacheFiles = array();
45
50 protected static $wildcardsIndex = null;
51
52 public static function definition()
53 {
54 static $definition = array( "fields" => array( "id" => array( 'name' => 'ID',
55 'datatype' => 'integer',
56 'default' => 0,
57 'required' => true ),
58 "source_url" => array( 'name' => "SourceURL",
59 'datatype' => 'string',
60 'default' => '',
61 'required' => true ),
62 "destination_url" => array( 'name' => "DestinationURL",
63 'datatype' => 'string',
64 'default' => '',
65 'required' => true ),
66 "type" => array( 'name' => "Type",
67 'datatype' => 'integer',
68 'default' => '0',
69 'required' => true ) ),
70 "keys" => array( "id" ),
71 'function_attributes' => array(),
72 "increment_key" => "id",
73 "class_name" => "eZURLWildcard",
74 "name" => "ezurlwildcard" );
75 return $definition;
76 }
77
83 public function asArray()
84 {
85 return array( 'id' => $this->attribute( 'id' ),
86 'source_url' => $this->attribute( 'source_url' ),
87 'destination_url' => $this->attribute( 'destination_url' ),
88 'type' => $this->attribute( 'type' ) );
89 }
90
94 public function store( $fieldFilters = null )
95 {
96 eZPersistentObject::store( $fieldFilters );
97 }
98
106 static function cleanup( $baseURL )
107 {
108 $db = eZDB::instance();
109 $baseURLText = $db->escapeString( $baseURL . "/*" );
110 $sql = "DELETE FROM ezurlwildcard
111 WHERE source_url = '$baseURLText'";
112 $db->query( $sql );
113 self::expireCache();
114 }
115
120 public static function removeAll()
121 {
122 eZPersistentObject::removeObject( self::definition() );
123 self::expireCache();
124 }
125
131 public static function removeByIDs( $idList )
132 {
133 if ( !is_array( $idList ) )
134 return;
135
136 while ( count( $idList ) > 0 )
137 {
138 // remove by portion of 100 rows.
139 $ids = array_splice( $idList, 0, 100 );
140
141 $conditions = array( 'id' => array( $ids ) );
142
143 eZPersistentObject::removeObject( self::definition(),
144 $conditions );
145 }
146 }
147
154 public static function fetch( $id, $asObject = true )
155 {
156 return eZPersistentObject::fetchObject( self::definition(),
157 null,
158 array( "id" => $id ),
159 $asObject );
160 }
161
168 public static function fetchBySourceURL( $url, $asObject = true )
169 {
170 return eZPersistentObject::fetchObject( self::definition(),
171 null,
172 array( "source_url" => $url ),
173 $asObject );
174 }
175
183 public static function fetchList( $offset = false, $limit = false, $asObject = true )
184 {
185 return eZPersistentObject::fetchObjectList( self::definition(),
186 null,
187 null,
188 null,
189 array( 'offset' => $offset, 'length' => $limit ),
190 $asObject );
191 }
192
197 public static function fetchListCount()
198 {
199 $rows = eZPersistentObject::fetchObjectList( self::definition(),
200 array(),
201 null,
202 false,
203 null,
204 false, false,
205 array( array( 'operation' => 'count( * )',
206 'name' => 'count' ) ) );
207 return $rows[0]['count'];
208 }
209
217 public static function translate( &$uri )
218 {
219 $result = false;
220
221 // get uri string
222 $uriString = ( $uri instanceof eZURI ) ? $uri->elements() : $uri;
223 $uriString = eZURLAliasML::cleanURL( $uriString );
224
225 eZDebugSetting::writeDebug( 'kernel-urltranslator', "input uriString: '$uriString'", __METHOD__ );
226
227 if ( !$wildcards = self::wildcardsIndex() )
228 {
229 eZDebugSetting::writeDebug( 'kernel-urltranslator', "no match callbacks", __METHOD__ );
230 return false;
231 }
232
233 $ini = eZINI::instance();
234 $iteration = $ini->variable( 'URLTranslator', 'MaximumWildcardIterations' );
235
236 eZDebugSetting::writeDebug( 'kernel-urltranslator', "MaximumWildcardIterations: '$iteration'", __METHOD__ );
237
238 // translate
239 $urlTranslated = false;
240 while ( !$urlTranslated && $iteration >= 0 )
241 {
242 foreach ( $wildcards as $wildcardNum => $wildcard )
243 {
244 if ( preg_match( $wildcard, $uriString ) )
245 {
246 eZDebugSetting::writeDebug( 'kernel-urltranslator', "matched with: '$wildcard'", __METHOD__ );
247
248 // get new $uriString from wildcard
249 self::translateWithCache( $wildcardNum, $uriString, $wildcardInfo, $wildcard );
250
251 eZDebugSetting::writeDebug( 'kernel-urltranslator', "new uri string: '$uriString'", __METHOD__ );
252
253 // optimization: don't try further translation if wildcard type is 'forward'
254 if ( $wildcardInfo['type'] == self::TYPE_FORWARD )
255 {
256 $urlTranslated = true;
257 break;
258 }
259
260 // try to tranlsate
261 if ( $urlTranslated = eZURLAliasML::translate( $uriString ) )
262 {
263 // success
264 eZDebugSetting::writeDebug( 'kernel-urltranslator', "uri is translated to '$uriString' with result '$urlTranslated'", __METHOD__ );
265 break;
266 }
267
268 eZDebugSetting::writeDebug( 'kernel-urltranslator', "uri is not translated, trying another wildcard", __METHOD__ );
269
270 // translation failed. Try to match new $uriString with another wildcard.
271 --$iteration;
272 continue 2;
273 }
274 }
275
276 // we here if non of the wildcards is matched
277 break;
278 }
279
280 // check translation result
281 // NOTE: 'eZURLAliasML::translate'(see above) can return 'true', 'false' or new url(in case of 'error/301').
282 // $urlTranslated can also be 'false' if no wildcard is matched.
283 if ( $urlTranslated )
284 {
285 // check wildcard type and set appropriate $result and $uriString
286 $wildcardType = $wildcardInfo['type'];
287
288 eZDebugSetting::writeDebug( 'kernel-urltranslator', "wildcard type: $wildcardType", __METHOD__ );
289
290 switch ( $wildcardType )
291 {
292 case self::TYPE_FORWARD:
293 {
294 // do redirect:
295 // => set $result to translated uri
296 // => set uri string to a MOVED PERMANENTLY HTTP code
297 $result = $uriString;
298 $uriString = 'error/301';
299 }
300 break;
301
302 default:
303 {
304 eZDebug::writeError( 'Invalid wildcard type.', __METHOD__ );
305 // no break, using eZURLWildcard::TYPE_DIRECT as fallback
306 }
307 case self::TYPE_DIRECT:
308 {
309 $result = $urlTranslated;
310 // $uriString already has correct value
311 break;
312 }
313 }
314 }
315 else
316 {
317 // we are here if:
318 // - input url is not matched with any wildcard;
319 // - url is matched with wildcard and:
320 // - points to module
321 // - invalide url
322 eZDebugSetting::writeDebug( 'kernel-urltranslator', "wildcard is not translated", __METHOD__ );
323 $result = false;
324 }
325
326 // set value back to $uri
327 if ( $uri instanceof eZURI )
328 {
329 $uri->setURIString( $uriString, false );
330 }
331 else
332 {
333 $uri = $uriString;
334 }
335
336 eZDebugSetting::writeDebug( 'kernel-urltranslator', "finished with url '$uriString' and result '$result'", __METHOD__ );
337
338 return $result;
339 }
340
350 protected static function cacheInfo()
351 {
352 static $cacheInfo = null;
353
354 if ( $cacheInfo == null )
355 {
356 $cacheDir = eZSys::cacheDirectory();
357 $ini = eZINI::instance();
358 $keys = array( 'implementation' => $ini->variable( 'DatabaseSettings', 'DatabaseImplementation' ),
359 'server' => $ini->variable( 'DatabaseSettings', 'Server' ),
360 'database' => $ini->variable( 'DatabaseSettings', 'Database' ) );
361 $wildcardKey = md5( implode( "\n", $keys ) );
362 $wildcardCacheDir = "$cacheDir/wildcard";
363 $wildcardCacheFile = "wildcard_$wildcardKey";
364 $wildcardCachePath = "$wildcardCacheDir/$wildcardCacheFile";
365 $cacheInfo = array( 'dir' => $wildcardCacheDir,
366 'file' => $wildcardCacheFile,
367 'path' => $wildcardCachePath,
368 'keys' => $keys );
369 }
370
371 return $cacheInfo;
372 }
373
378 protected static function cacheInfoDirectories( &$wildcardCacheDir, &$wildcardCacheFile, &$wildcardCachePath, &$wildcardKeys )
379 {
380 $info = self::cacheInfo();
381 $wildcardCacheDir = $info['dir'];
382 $wildcardCacheFile = $info['file'];
383 $wildcardCachePath = $info['path'];
384 $wildcardKeys = $info['keys'];
385 }
386
392 public static function expireCache()
393 {
394 $handler = eZExpiryHandler::instance();
395 $handler->setTimestamp( self::CACHE_SIGNATURE, time() );
396 $handler->store();
397
398 self::$wildcardsIndex = null;
399 }
400
405 protected static function expiryTimestamp()
406 {
407 $handler = eZExpiryHandler::instance();
408 if ( $handler->hasTimestamp( self::CACHE_SIGNATURE ) )
409 {
410 $ret = $handler->timestamp( self::CACHE_SIGNATURE );
411 }
412 else
413 {
414 $ret = false;
415 }
416 return $ret;
417 }
418
425 protected static function wildcardsIndex()
426 {
427 if ( self::$wildcardsIndex === null )
428 {
429 $cacheIndexFile = self::loadCacheFile();
430
431 // if NULL is returned, the cache doesn't exist or isn't valid
432 self::$wildcardsIndex = $cacheIndexFile->processFile( array( __CLASS__, 'fetchCacheFile' ), self::expiryTimestamp() );
433 if ( self::$wildcardsIndex === null )
434 {
435 // This will generate and return the index, and store the cache
436 // files for the different wildcards for later use
437 self::$wildcardsIndex = self::createWildcardsIndex();
438 }
439 }
440
441 return self::$wildcardsIndex;
442 }
443
457 protected static function createWildcardsIndex()
458 {
459 self::cacheInfoDirectories( $wildcardCacheDir, $wildcardCacheFile, $wildcardCachePath, $wildcardKeys );
460 if ( !file_exists( $wildcardCacheDir ) )
461 {
462 eZDir::mkdir( $wildcardCacheDir, false, true );
463 }
464
465 // Index file (wildcard_md5_index.php)
466 $wildcardsIndex = array();
467
468 $limit = self::WILDCARDS_PER_CACHE_FILE;
469 $offset = 0;
470 $cacheFilesCount = 0;
471 $wildcardNum = 0;
472 while( 1 )
473 {
474 $wildcards = self::fetchList( $offset, $limit, false );
475 if ( count( $wildcards ) === 0 )
476 {
477 break;
478 }
479
480 // sub cache file (wildcard_md5_<i>.php)
481 $wildcardDetails = array();
482 $currentSubCacheFile = self::loadCacheFile( $cacheFilesCount );
483 foreach ( $wildcards as $wildcard )
484 {
485 $wildcardsIndex[] = self::matchRegexpCode( $wildcard );
486 $wildcardDetails[$wildcardNum] = self::matchReplaceCode( $wildcard );
487
488 ++$wildcardNum;
489 }
490 $binaryData = "<" . "?php\nreturn ". var_export( $wildcardDetails, true ) . ";\n?" . ">\n";
491 $currentSubCacheFile->storeContents( $binaryData, "wildcard-cache-$cacheFilesCount", 'php', true );
492
493 $offset += $limit;
494 ++$cacheFilesCount;
495 }
496
497 $indexCacheFile = self::loadCacheFile();
498 $indexBinaryData = "<" . "?php\nreturn ". var_export( $wildcardsIndex, true ) . ";\n?" . ">\n";
499 $indexCacheFile->storeContents( $indexBinaryData, "wildcard-cache-index", 'php', true );
500
501 return $wildcardsIndex;
502 // end index cache file
503 }
504
513 protected static function matchRegexpCode( $wildcard )
514 {
515 $matchWilcard = $wildcard['source_url'];
516 $matchWilcardList = explode( "*", $matchWilcard );
517 $regexpList = array();
518 foreach ( $matchWilcardList as $matchWilcardItem )
519 {
520 $regexpList[] = preg_quote( $matchWilcardItem, '#' );
521 }
522 $matchRegexp = implode( '(.*)', $regexpList );
523
524 return "#^$matchRegexp#i";
525 }
526
539 protected static function matchReplaceCode( $wildcard )
540 {
541 $return = array();
542
543 $replaceWildcardList = preg_split( "#{([0-9]+)}#", $wildcard['destination_url'], false, PREG_SPLIT_DELIM_CAPTURE );
544
545 $replaceArray = array();
546 foreach ( $replaceWildcardList as $index => $replaceWildcardItem )
547 {
548 // even values are placeholders
549 if ( ( $index % 2 ) == 0 )
550 {
551 $replaceArray[] = $replaceWildcardItem;
552 }
553 else
554 {
555 $replaceArray[] = "\${$replaceWildcardItem}";
556 }
557 }
558 $replaceCode = implode( '', $replaceArray );
559
560 $return['uri'] = $replaceCode;
561 $return['info'] = $wildcard;
562
563 return $return;
564 }
565
585 protected static function translateWithCache( $wildcardNum, &$uri, &$wildcardInfo, $matchRegexp )
586 {
587 eZDebugSetting::writeDebug( 'kernel-urltranslator', "wildcardNum = $wildcardNum, uri = $uri", __METHOD__ );
588
589 $cacheFileNum = (int) ( $wildcardNum / self::WILDCARDS_PER_CACHE_FILE );
590
591 eZDebugSetting::writeDebug( 'kernel-urltranslator', "cacheFileNum = $cacheFileNum", __METHOD__ );
592
593 $cacheFile = self::loadCacheFile( $cacheFileNum );
594 $wildcardsInfos = $cacheFile->processFile( array( __CLASS__, 'fetchCacheFile' ) );
595
596 if ( !isset( $wildcardsInfos[$wildcardNum] ) )
597 {
598 eZDebug::writeError( "An error occured: the requested wildcard couldn't be found", __METHOD__ );
599 return false;
600 }
601
602 // @todo Try to replace this with a preg_replace in order to get rid of eval()
603 $replaceRegexp = $wildcardsInfos[$wildcardNum]['uri'];
604 $uri = preg_replace( $matchRegexp, $replaceRegexp, $uri );
605 $wildcardInfo = $wildcardsInfos[$wildcardNum]['info'];
606
607 eZDebugSetting::writeDebug( 'kernel-urltranslator', "found wildcard: " . var_export( $wildcardInfo, true ), __METHOD__ );
608
609 return true;
610 }
611
620 protected static function loadCacheFile( $cacheID = 'index' )
621 {
622 if ( isset( self::$cacheFiles[$cacheID] ) )
623 {
624 return self::$cacheFiles[$cacheID];
625 }
626
627 $info = self::cacheInfo();
628 $cacheFileName = $info['path'] . '_' . $cacheID . '.php';
629
630 self::$cacheFiles[$cacheID] = eZClusterFileHandler::instance( $cacheFileName );
631 return self::$cacheFiles[$cacheID];
632 }
633
642 public static function fetchCacheFile( $filepath )
643 {
644 return include( $filepath );
645 }
646
653 public static function wildcardExists( $uriString )
654 {
655 $wildcardIndex = self::wildcardsIndex();
656 foreach ( $wildcardIndex as $preg )
657 {
658 if ( preg_match( $preg, $uriString ) )
659 {
660 return true;
661 }
662 }
663 return false;
664 }
665 }
666
667 ?>
eZClusterFileHandler\instance
static instance( $filename=false)
Definition: ezclusterfilehandler.php:21
eZDB\instance
static instance( $databaseImplementation=false, $databaseParameters=false, $forceNewInstance=false)
Definition: ezdb.php:117
eZDebugSetting\writeDebug
static writeDebug( $conditionName, $string, $label="")
Definition: ezdebugsetting.php:127
eZDebug\writeError
static writeError( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:545
eZDir\mkdir
static mkdir( $dir, $perm=false, $recursive=false)
Definition: ezdir.php:73
eZPersistentObject
Definition: ezpersistentobject.php:33
eZPersistentObject\fetchObject
static fetchObject( $def, $field_filters, $conds, $asObject=true, $grouping=null, $custom_fields=null)
Definition: ezpersistentobject.php:213
eZPersistentObject\store
store( $fieldFilters=null)
Definition: ezpersistentobject.php:304
eZPersistentObject\removeObject
static removeObject( $def, $conditions=null, $extraConditions=null)
Definition: ezpersistentobject.php:271
eZPersistentObject\count
static count( $def, $conds=null, $field=null)
Definition: ezpersistentobject.php:187
eZPersistentObject\attribute
attribute( $attr, $noFunction=false)
Definition: ezpersistentobject.php:1329
eZPersistentObject\fetchObjectList
static fetchObjectList( $def, $field_filters=null, $conds=null, $sorts=null, $limit=null, $asObject=true, $grouping=false, $custom_fields=null, $custom_tables=null, $custom_conds=null)
Definition: ezpersistentobject.php:806
eZSys\cacheDirectory
static cacheDirectory()
Definition: ezsys.php:527
eZURI
Definition: ezuri.php:28
eZURLAliasML\cleanURL
static cleanURL( $url)
Definition: ezurlaliasml.php:2182
eZURLAliasML\translate
static translate(&$uri, $reverse=false)
Definition: ezurlaliasml.php:1491
eZURLWildcard
Handles URL alias wildcards in eZ Publish.
Definition: ezurlwildcard.php:19
eZURLWildcard\asArray
asArray()
Definition: ezurlwildcard.php:83
eZURLWildcard\fetchList
static fetchList( $offset=false, $limit=false, $asObject=true)
Definition: ezurlwildcard.php:183
eZURLWildcard\cacheInfoDirectories
static cacheInfoDirectories(&$wildcardCacheDir, &$wildcardCacheFile, &$wildcardCachePath, &$wildcardKeys)
Definition: ezurlwildcard.php:378
eZURLWildcard\translate
static translate(&$uri)
Definition: ezurlwildcard.php:217
eZURLWildcard\wildcardsIndex
static wildcardsIndex()
Definition: ezurlwildcard.php:425
eZURLWildcard\removeByIDs
static removeByIDs( $idList)
Definition: ezurlwildcard.php:131
eZURLWildcard\fetch
static fetch( $id, $asObject=true)
Definition: ezurlwildcard.php:154
eZURLWildcard\removeAll
static removeAll()
Definition: ezurlwildcard.php:120
eZURLWildcard\expireCache
static expireCache()
Definition: ezurlwildcard.php:392
eZURLWildcard\matchReplaceCode
static matchReplaceCode( $wildcard)
Definition: ezurlwildcard.php:539
eZURLWildcard\CACHE_SIGNATURE
const CACHE_SIGNATURE
Definition: ezurlwildcard.php:38
eZURLWildcard\store
store( $fieldFilters=null)
Definition: ezurlwildcard.php:94
eZURLWildcard\wildcardExists
static wildcardExists( $uriString)
Definition: ezurlwildcard.php:653
eZURLWildcard\translateWithCache
static translateWithCache( $wildcardNum, &$uri, &$wildcardInfo, $matchRegexp)
Definition: ezurlwildcard.php:585
eZURLWildcard\$cacheFiles
static $cacheFiles
Definition: ezurlwildcard.php:44
eZURLWildcard\cleanup
static cleanup( $baseURL)
Definition: ezurlwildcard.php:106
eZURLWildcard\expiryTimestamp
static expiryTimestamp()
Definition: ezurlwildcard.php:405
eZURLWildcard\TYPE_DIRECT
const TYPE_DIRECT
Definition: ezurlwildcard.php:32
eZURLWildcard\definition
static definition()
Definition: ezurlwildcard.php:52
eZURLWildcard\matchRegexpCode
static matchRegexpCode( $wildcard)
Definition: ezurlwildcard.php:513
eZURLWildcard\TYPE_FORWARD
const TYPE_FORWARD
Definition: ezurlwildcard.php:31
eZURLWildcard\createWildcardsIndex
static createWildcardsIndex()
Definition: ezurlwildcard.php:457
eZURLWildcard\loadCacheFile
static loadCacheFile( $cacheID='index')
Definition: ezurlwildcard.php:620
eZURLWildcard\$wildcardsIndex
static $wildcardsIndex
Definition: ezurlwildcard.php:50
eZURLWildcard\fetchCacheFile
static fetchCacheFile( $filepath)
Definition: ezurlwildcard.php:642
eZURLWildcard\cacheInfo
static cacheInfo()
Definition: ezurlwildcard.php:350
eZURLWildcard\fetchListCount
static fetchListCount()
Definition: ezurlwildcard.php:197
eZURLWildcard\WILDCARDS_PER_CACHE_FILE
const WILDCARDS_PER_CACHE_FILE
Definition: ezurlwildcard.php:24
eZURLWildcard\fetchBySourceURL
static fetchBySourceURL( $url, $asObject=true)
Definition: ezurlwildcard.php:168
eZURLWildcard\TYPE_NONE
const TYPE_NONE
Definition: ezurlwildcard.php:30
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.