216 lines
6.1 KiB
PHP
216 lines
6.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Time and date internationalization management library
|
|
*
|
|
* @author Timely Network Inc
|
|
* @since 2012.10.09
|
|
*
|
|
* @package AllInOneCalendar
|
|
* @subpackage AllInOneCalendar.Lib.Utility
|
|
*/
|
|
class Ai1ec_Time_I18n_Utility extends Ai1ec_Base {
|
|
|
|
/**
|
|
* @var char Separator to wrap unique keys and avoid collisions
|
|
* EOT is used instead of NUL, as NUL is used by `date()`
|
|
* functions family as guard and causes memory leaks.
|
|
*/
|
|
protected $_separator = "\004";
|
|
|
|
/**
|
|
* @var array Map of keys, used by date methods
|
|
*/
|
|
protected $_keys = array();
|
|
|
|
/**
|
|
* @var array Map of keys for substition
|
|
*/
|
|
protected $_skeys = array();
|
|
|
|
/**
|
|
* @var string Format to use when calling `date_i18n()`
|
|
*/
|
|
protected $_format = NULL;
|
|
|
|
/**
|
|
* @var Ai1ec_Memory_Utility Parsed time entries
|
|
*/
|
|
protected $_memory = NULL;
|
|
|
|
/**
|
|
* @var Ai1ec_Memory_Utility Parsed format entries
|
|
*/
|
|
protected $_transf = NULL;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* Initialize internal memory objects and date keys.
|
|
*
|
|
* @param Ai1ec_Memory_Utility $memory Optionally inject memory to use
|
|
*
|
|
* @return void Constructor does not return
|
|
*/
|
|
public function __construct(
|
|
Ai1ec_Registry_Object $registry,
|
|
Ai1ec_Cache_Memory $memory = null
|
|
) {
|
|
parent::__construct( $registry );
|
|
if ( NULL === $memory ) {
|
|
$memory = $this->_registry->get( 'cache.memory', 120 ); // 30 * 4
|
|
}
|
|
$this->_memory = $memory;
|
|
$this->_transf = $this->_registry->get( 'cache.memory' );
|
|
$this->_keys = $this->_initialize_keys();
|
|
$this->_skeys = $this->_initialize_keys(
|
|
$this->_separator,
|
|
$this->_separator
|
|
);
|
|
$this->_format = implode( $this->_separator, $this->_keys );
|
|
}
|
|
|
|
/**
|
|
* format method
|
|
*
|
|
* Convenient wrapper for `date_i18n()`, which caches both faster format
|
|
* version and response for {$timestamp} and {$is_gmt} combination.
|
|
*
|
|
* @param string $format Format string to output timestamp in
|
|
* @param int $timestamp UNIX timestamp to output in given format
|
|
* @param bool $is_gmt Set to true, to treat {$timestamp} as GMT
|
|
*
|
|
* @return string Formatted date-time entry
|
|
*/
|
|
public function format( $format, $timestamp = false, $is_gmt = false ) {
|
|
$time_elements = $this->parse( $timestamp, $is_gmt );
|
|
$local_format = $this->_safe_format( $format );
|
|
return str_replace( $this->_skeys, $time_elements, $local_format );
|
|
}
|
|
|
|
/**
|
|
* parse method
|
|
*
|
|
* Parse given timestamp into I18n date/time values map.
|
|
*
|
|
* @param int $timestamp Timestamp to parse
|
|
* @param bool $is_gmt Set to true, to treat value as present in GMT
|
|
*
|
|
* @return array Map of date format keys and corresponding time values
|
|
*/
|
|
public function parse( $timestamp = false, $is_gmt = false ) {
|
|
$timestamp = (int)$timestamp;
|
|
if ( $timestamp <= 0 ) {
|
|
$timestamp = $this->_registry->get( 'date.system' )->current_time();
|
|
}
|
|
$cache_key = $timestamp . "\0" . $is_gmt;
|
|
if ( NULL === ( $record = $this->_memory->get( $cache_key ) ) ) {
|
|
$record = array_combine(
|
|
$this->_keys,
|
|
explode(
|
|
$this->_separator,
|
|
date_i18n( $this->_format, $timestamp, $is_gmt )
|
|
)
|
|
);
|
|
$this->_memory->set( $cache_key, $record );
|
|
}
|
|
return $record;
|
|
}
|
|
|
|
/**
|
|
* _safe_format method
|
|
*
|
|
* Prepare safe format value, to use in substitutions.
|
|
* In prepared string special values are wrapped by {$_separator} to allow
|
|
* fast replacement methods, using binary search.
|
|
*
|
|
* @param string $format Given format to polish
|
|
*
|
|
* @return string Modified format, with special keys wrapped in bin fields
|
|
*/
|
|
protected function _safe_format( $format ) {
|
|
if ( NULL === ( $safe = $this->_transf->get( $format ) ) ) {
|
|
$safe = '';
|
|
$state = 0;
|
|
$separator = $this->_separator;
|
|
$length = strlen( $format );
|
|
for ( $index = 0; $index < $length; $index++ ) {
|
|
if ( $state > 0 ) {
|
|
--$state;
|
|
}
|
|
$current = $format{$index};
|
|
if ( 0 === $state ) {
|
|
if ( '\\' === $current ) {
|
|
$state = 2;
|
|
} elseif ( isset( $this->_keys[$current] ) ) {
|
|
$current = $separator . $current . $separator;
|
|
}
|
|
}
|
|
if ( 2 !== $state ) {
|
|
$safe .= $current;
|
|
}
|
|
}
|
|
$this->_transf->set( $format, $safe );
|
|
}
|
|
return $safe;
|
|
}
|
|
|
|
/**
|
|
* _initialize_keys method
|
|
*
|
|
* Prepare list of keys, used by date functions.
|
|
* Optionally wrap values (keys are the same, always).
|
|
*
|
|
* @param string $prepend Prefix to date key
|
|
* @param string $append Suffix to date key
|
|
*
|
|
* @return array Map of date keys
|
|
*/
|
|
protected function _initialize_keys( $prepend = '', $append = '' ) {
|
|
$keys = array(
|
|
'd',
|
|
'D',
|
|
'j',
|
|
'l',
|
|
'N',
|
|
'S',
|
|
'w',
|
|
'z',
|
|
'W',
|
|
'F',
|
|
'm',
|
|
'M',
|
|
'n',
|
|
't',
|
|
'L',
|
|
'o',
|
|
'Y',
|
|
'y',
|
|
'a',
|
|
'A',
|
|
'B',
|
|
'g',
|
|
'G',
|
|
'h',
|
|
'H',
|
|
'i',
|
|
's',
|
|
'u',
|
|
'e',
|
|
'I',
|
|
'O',
|
|
'P',
|
|
'T',
|
|
'Z',
|
|
'c',
|
|
'r',
|
|
'U',
|
|
);
|
|
$map = array();
|
|
foreach ( $keys as $key ) {
|
|
$map[$key] = $prepend . $key . $append;
|
|
}
|
|
return $map;
|
|
}
|
|
|
|
}
|