181
wp-content/plugins/all-in-one-event-calendar/lib/parser/date.php
Normal file
181
wp-content/plugins/all-in-one-event-calendar/lib/parser/date.php
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Date/Time format parser
|
||||
*
|
||||
* @author Time.ly Network, Inc.
|
||||
* @since 2.0
|
||||
* @package Ai1EC
|
||||
* @subpackage Ai1EC.Parser
|
||||
*/
|
||||
class Ai1ec_Parser_Date {
|
||||
|
||||
/**
|
||||
* @var string Character separating tokens.
|
||||
*/
|
||||
protected $_token_separator;
|
||||
|
||||
/**
|
||||
* @var string Character specifying need for localization.
|
||||
*/
|
||||
protected $_localize_indicator;
|
||||
|
||||
/**
|
||||
* @var array Map of input and parsed formats.
|
||||
*/
|
||||
protected $_parsed = array();
|
||||
|
||||
/**
|
||||
* @var array Map of I18n-able format specifiers.
|
||||
*/
|
||||
protected $_i18nable_formats = array(
|
||||
'D' => array( 'w', null ),
|
||||
'F' => array( 'm', 'get_month' ),
|
||||
'l' => array( 'w', 'get_weekday' ),
|
||||
'M' => array( 'm', null ),
|
||||
'a' => array( 'a', 'get_meridiem' ),
|
||||
'A' => array( 'A', 'get_meridiem' ),
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @return void Method does not return.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->_token_separator = chr( 12 );
|
||||
$this->_localize_indicator = chr( 11 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get i18n-safe format string.
|
||||
*
|
||||
* NOTICE: this method caches result of {@see self::parse()} call.
|
||||
*
|
||||
* @param string $format Requested format.
|
||||
*
|
||||
* @return string Format to use in `date`-like calls.
|
||||
*/
|
||||
public function get_format( $format ) {
|
||||
if ( ! isset( $this->_parsed[$format] ) ) {
|
||||
$this->_parsed[$format] = $this->parse( $format );
|
||||
}
|
||||
return $this->_parsed[$format];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse date-time into i18n-safe format string.
|
||||
*
|
||||
* @param string $format Input format.
|
||||
*
|
||||
* @return string Format to use in `date`-like calls.
|
||||
*/
|
||||
public function parse( $format ) {
|
||||
$parsed = '';
|
||||
$case = 0;
|
||||
for ( $idx = 0, $len = strlen( $format ); $idx < $len; $idx++ ) {
|
||||
$char = $format{$idx};
|
||||
if ( 1 !== $case ) {
|
||||
if ( '\\' === $char ) {
|
||||
$case = 2;
|
||||
} else {
|
||||
$char = $this->get_i18n_name( $char );
|
||||
}
|
||||
}
|
||||
$parsed .= $char;
|
||||
if ( $case > 0 ) {
|
||||
--$case;
|
||||
}
|
||||
}
|
||||
return trim( $parsed, $this->_token_separator );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove binary characters and add I18n values to formatted string.
|
||||
*
|
||||
* @param string $formatted Formatted datetime string.
|
||||
*
|
||||
* @return string Safe for use format value.
|
||||
*/
|
||||
public function squeeze( $formatted ) {
|
||||
$output = '';
|
||||
$tokens = explode( $this->_token_separator, $formatted );
|
||||
foreach ( $tokens as $token ) {
|
||||
$output .= $this->get_i18n_value( $token );
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return rendering-ready formatted string token value.
|
||||
*
|
||||
* Method uses {@see self::localize()} to actually format I18n
|
||||
* parts when needed.
|
||||
*
|
||||
* @param string $token Formatting token.
|
||||
*
|
||||
* @return string I18n-ized value.
|
||||
*/
|
||||
public function get_i18n_value( $token ) {
|
||||
if ( isset( $token{0} ) && $this->_localize_indicator === $token{0} ) {
|
||||
$format = $token{1};
|
||||
$value = substr( $token, 2 );
|
||||
$token = $this->localize( $format, $value );
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get I18n value for token.
|
||||
*
|
||||
* @param string $format Original format specifier.
|
||||
* @param string $value Value to use in I18n query.
|
||||
*
|
||||
* @return string I18n-formatted string.
|
||||
*/
|
||||
public function localize( $format, $value ) {
|
||||
global $wp_locale;
|
||||
if (
|
||||
isset( $this->_i18nable_formats[$format] ) &&
|
||||
isset( $this->_i18nable_formats[$format][1] )
|
||||
) {
|
||||
return $wp_locale->{$this->_i18nable_formats[$format][1]}( $value );
|
||||
}
|
||||
switch ( $format ) {
|
||||
case 'M':
|
||||
return $wp_locale->get_month_abbrev(
|
||||
$wp_locale->get_month( $value )
|
||||
);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
return $wp_locale->get_weekday_abbrev(
|
||||
$wp_locale->get_weekday( $value )
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
// nop
|
||||
}
|
||||
return $value; // fail-safe
|
||||
}
|
||||
|
||||
/**
|
||||
* Get optionally binary-quoted string for formatting inputs.
|
||||
*
|
||||
* @param string $format Originally requested formatting token.
|
||||
*
|
||||
* @return string Token to use in formatting query.
|
||||
*/
|
||||
public function get_i18n_name( $format ) {
|
||||
if ( isset( $this->_i18nable_formats[$format] ) ) {
|
||||
return $this->_token_separator .
|
||||
$this->_localize_indicator . // speed parsing token
|
||||
'\\' . $format . // backslashed value for recovery
|
||||
$this->_i18nable_formats[$format][0] . // formattable token
|
||||
$this->_token_separator;
|
||||
}
|
||||
return $format;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Frequency parser.
|
||||
*
|
||||
* @author Time.ly Network, Inc.
|
||||
* @since 2.0
|
||||
* @instantiator new
|
||||
* @package Ai1EC
|
||||
* @subpackage Ai1EC.Parser
|
||||
*/
|
||||
class Ai1ec_Frequency_Utility {
|
||||
|
||||
/**
|
||||
* @var array Map of default multipliers
|
||||
*/
|
||||
protected $_multipliers = array(
|
||||
's' => 1, // take care, to always have an identifier with unit of `1`
|
||||
'm' => 60,
|
||||
'h' => 3600,
|
||||
'd' => 86400,
|
||||
'w' => 604800,
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array Map of WordPress native multipliers
|
||||
*/
|
||||
protected $_wp_names = array(
|
||||
'hourly' => array(
|
||||
'item' => array( 'h' => 1 ),
|
||||
'seconds' => 3600
|
||||
),
|
||||
'twicedaily' => array(
|
||||
'item' => array( 'd' => 0.5 ),
|
||||
'seconds' => 43200
|
||||
),
|
||||
'daily' => array(
|
||||
'item' => array( 'd' => 1 ),
|
||||
'seconds' => 86400
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* @var string One letter code for lowest available quantifier
|
||||
*/
|
||||
protected $_lowest_quantifier = 's';
|
||||
|
||||
/**
|
||||
* @var array Parsed representation - quantifiers and their amounts
|
||||
*/
|
||||
protected $_parsed = array();
|
||||
|
||||
/**
|
||||
* Inject different multiplier
|
||||
*
|
||||
* Add multiplier, to parseable characters
|
||||
*
|
||||
* @param string $letter Letter (single ASCII letter) to allow as quantifier
|
||||
* @param int $quant Number of seconds quantifier represents
|
||||
*
|
||||
* @return Ai1ec_Frequency_Utility Instance of self for chaining
|
||||
*
|
||||
* @throws Ai1ec_Invalid_Argument_Exception If first argument is not
|
||||
* an ASCII letter.
|
||||
*/
|
||||
public function add_multiplier( $letter, $quant ) {
|
||||
$letter = substr( (string)$letter, 0, 1 );
|
||||
$quant = (int)$quant;
|
||||
if ( $quant < 0 || ! preg_match( '/^[a-z]$/i', $letter ) ) {
|
||||
throw new Ai1ec_Invalid_Argument_Exception(
|
||||
'First argument to add_multiplier must be ASCII letter' .
|
||||
'(a-zA-Z), and second - an integer'
|
||||
);
|
||||
}
|
||||
$this->_multipliers[$letter] = $quant;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse user input
|
||||
*
|
||||
* Convert arbitrary user input (i.e. "2w 10h") to internal representation
|
||||
*
|
||||
* @param string $input User input for frequency
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public function parse( $input ) {
|
||||
$input = strtolower(
|
||||
preg_replace(
|
||||
'|(\d*\.?\d+)\s+([a-z])|',
|
||||
'$1$2',
|
||||
trim( $input )
|
||||
)
|
||||
);
|
||||
if ( isset( $this->_wp_names[$input] ) ) {
|
||||
$this->_parsed = $this->_wp_names[$input]['item'];
|
||||
return true;
|
||||
}
|
||||
$match = $this->_match( $input );
|
||||
if ( ! $match ) {
|
||||
return false;
|
||||
}
|
||||
$this->_parsed = $match;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert parsed input to corresponding seconds
|
||||
*
|
||||
* @return int Number of seconds corresponding to user input
|
||||
*/
|
||||
public function to_seconds() {
|
||||
$seconds = 0;
|
||||
foreach ( $this->_parsed as $quantifier => $number ) {
|
||||
$seconds += $number * $this->_multipliers[$quantifier];
|
||||
}
|
||||
$seconds = (int)$seconds; // discard any fractional part
|
||||
return $seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert parsed input to unified format
|
||||
*
|
||||
* @return string Unified output format
|
||||
*/
|
||||
public function to_string() {
|
||||
$seconds = $this->to_seconds();
|
||||
if ( $wp_name = $this->match_wp_native_interval( $seconds ) ) {
|
||||
return $wp_name;
|
||||
}
|
||||
$reverse_quant = array_flip( $this->_multipliers );
|
||||
krsort( $reverse_quant );
|
||||
$output = array();
|
||||
foreach ( $reverse_quant as $duration => $quant ) {
|
||||
if ( $duration > $seconds ) {
|
||||
continue;
|
||||
}
|
||||
$modded = (int)( $seconds / $duration );
|
||||
if ( $modded > 0 ) {
|
||||
$output[] = $modded . $quant;
|
||||
$seconds -= $modded * $duration;
|
||||
if ( $seconds <= 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode( ' ', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns seconds interval to native wp name,
|
||||
*
|
||||
* @param int $seconds Value.
|
||||
*
|
||||
* @return bool|string False or name.
|
||||
*/
|
||||
public function match_wp_native_interval( $seconds ) {
|
||||
if ( empty( $this->_parsed ) ) {
|
||||
return false;
|
||||
}
|
||||
$response = false;
|
||||
foreach ( $this->_wp_names as $name => $interval ) {
|
||||
if ( $interval['seconds'] === $seconds ) {
|
||||
$response = $name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract time identifiers from input string
|
||||
*
|
||||
* Given arbitrary string collects known identifiers preceeded by numeric
|
||||
* value and counts these. For example, given input '2d 1h 2h' will yield
|
||||
* an `array( 'd' => 2, 'h' => 3 )`, that is easy to parse.
|
||||
*
|
||||
* @param string $input User supplied input
|
||||
*
|
||||
* @return array Extracted time identifiers
|
||||
*/
|
||||
protected function _match( $input ) {
|
||||
$regexp = '/(\d*\.?\d+)([' .
|
||||
implode( '|', array_keys( $this->_multipliers ) ) .
|
||||
'])?/';
|
||||
$matches = NULL;
|
||||
if ( ! preg_match_all( $regexp, $input, $matches ) ) {
|
||||
return false;
|
||||
}
|
||||
$output = array();
|
||||
foreach ( $matches[0] as $key => $value ) {
|
||||
$quantifier = ( ! empty( $matches[2][$key] ) )
|
||||
? $matches[2][$key]
|
||||
: $this->_lowest_quantifier;
|
||||
if ( ! isset( $output[$quantifier] ) ) {
|
||||
$output[$quantifier] = 0;
|
||||
}
|
||||
$output[$quantifier] += $matches[1][$key];
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user