all-in-one-event-calendar/lib/routing/uri.php
2017-11-09 17:36:04 +01:00

228 lines
6.8 KiB
PHP

<?php
/**
* URI management class
*
* @author Time.ly Network Inc.
* @since 2.0
*
* @package AI1EC
* @subpackage AI1EC.Routing
*/
class Ai1ec_Uri
{
/**
* Set direction separator
*/
const DIRECTION_SEPARATOR = '~';
/**
* @var string Arguments (list) separator
*/
protected $_arguments_separator = '/';
/**
* Parse page to internal URI representation
*
* @param string $page Page URI to parse
*
* @return array|bool Parsed URI or false on failure
*/
public function parse( $page ) {
$result = array(
'base' => '',
'ai1ec' => array(),
'args' => null,
'hash' => null,
'_type' => 'args', // enum: args,hash,pretty
);
if ( false === ( $parsed = parse_url( $page ) ) ) {
return false;
}
if ( isset( $parsed['scheme'] ) ) {
if ( !isset( $parsed['host'] ) ) {
return false;
}
$result['base'] = $parsed['scheme'] . '://' . $parsed['host'];
}
if ( ! empty( $parsed['path'] ) ) {
if ( false !== strpos( $parsed['path'], self::DIRECTION_SEPARATOR ) ) {
$result['_type'] = 'pretty';
$elements = explode(
$this->_arguments_separator,
$parsed['path']
);
foreach ( $elements as $particle ) {
$sep = strpos( $particle, self::DIRECTION_SEPARATOR );
if ( false !== $sep ) {
$key = substr( $particle, 0, $sep );
$result['ai1ec'][$key] = substr( $particle, $sep + 1 );
} else {
$result['base'] .= $this->_arguments_separator .
$particle;
}
}
}
}
$query_pos = array(
'query' => 'args',
'fragment' => 'hash',
);
foreach ( $query_pos as $source => $destination ) {
if ( 'hash' === $destination ) {
$result['_type'] = $destination;
}
if ( ! empty( $parsed[$source] ) ) {
$result = Ai1ec_Utility_Array::deep_merge(
$result,
$this->parse_query_str( $parsed[$source], $destination )
);
}
}
return $result;
}
/**
* Produce query to use in URI
*
* @param array $parsed Internal query representation
*
* @return string Normalized URI
*/
public function write( array $parsed ) {
$uri = $parsed['base'];
if ( 'pretty' == $parsed['_type'] ) {
$uri = rtrim( $uri, $this->_arguments_separator );
foreach ( $parsed['ai1ec'] as $key => $value ) {
$uri .= $this->_arguments_separator .
$this->_clean_key( $key ) .
self::DIRECTION_SEPARATOR .
$this->_safe_uri_value( $value );
}
} else {
$place = $parsed['_type'];
$action = isset( $parsed['ai1ec']['action'] )
? $parsed['ai1ec']['action']
: NULL;
if ( empty( $action ) ) {
foreach ( array( 'args', 'hash' ) as $place ) {
if ( ! empty( $parsed[$place]['action'] ) ) {
$action = $parsed[$place]['action'];
break;
}
}
}
if ( empty( $action ) ) {
$action = 'uri_err';
}
if ( 0 !== strncmp( $action, 'ai1ec_', 6 ) ) {
$action = 'ai1ec_' . $action;
}
$combined_ai1ec = array();
foreach ( $parsed['ai1ec'] as $key => $value ) {
$combined_ai1ec[] = $this->_clean_key( $key ) .
self::DIRECTION_SEPARATOR . $this->_safe_uri_value( $value );
}
$combined_ai1ec = implode( '|', $combined_ai1ec );
$parsed[$place]['ai1ec'] = $combined_ai1ec;
if ( 'hash' === $place ) {
$parsed[$place]['action'] = $action;
}
unset( $combined_ai1ec, $place );
}
$arg_list = array(
'args' => '?',
'hash' => '#',
);
foreach ( $arg_list as $name => $separator ) {
if ( ! empty( $parsed[$name] ) ) {
$uri .= $separator . build_query( $parsed[$name] );
}
}
return $uri;
}
/**
* Convert query string to internal representation
*
* @param string $query Query to parse
* @param string $name Positional name (i.e. 'hash')
*
* @return array Parsed query map with 'ai1ec' and {$name} keys
*/
public function parse_query_str( $query, $name ) {
$result = array(
'ai1ec' => array(),
$name => array(),
);
$parsed = null;
parse_str( $query, $parsed );
foreach ( $parsed as $key => $value ) {
if ( 0 === strncmp( $key, 'ai1ec', 5 ) ) {
$result['_type'] = $name;
if ( ! is_array( $value ) ) {
if ( 'ai1ec' === $key ) {
$value_list = explode( '|', $value );
$value = array();
foreach ( $value_list as $entry ) {
list( $sub_key, $sub_value ) = explode(
self::DIRECTION_SEPARATOR,
$entry
);
$value[$sub_key] = $sub_value;
}
unset( $value_list );
} else {
$value = array( substr($key, 6) => $value );
}
}
$result['ai1ec'] = array_merge(
$result['ai1ec'],
$value
);
} else {
$result[$name][$key] = $value;
}
}
unset( $parsed );
return $result;
}
/**
* Create URI-safe value (scalar)
*
* @param mixed $value Value provided for URL
*
* @return string Value to use in URI
*/
protected function _safe_uri_value( $value ) {
if ( is_array( $value ) ) {
$value = implode(',', $value);
}
return $value;
}
/**
* Clean AI1EC sub-element key
*
* @param string $key Key to clean
*
* @return string Cleaned key to output
*/
protected function _clean_key( $key ) {
if ( 0 === strncmp( $key, 'ai1ec_', 6 ) ) {
$key = substr( $key, 6 );
}
return $key;
}
}