@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Calendar Http_Encoder wrapper.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.2
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Lib
|
||||
*/
|
||||
|
||||
class Ai1ec_HTTP_Encoder extends HTTP_Encoder {
|
||||
|
||||
/**
|
||||
* Overrides parent function and removed Content-Length header to avoid
|
||||
* some problems if our JavaScript is somehow prepended by 3rd party code.
|
||||
*
|
||||
* @return void Method does not return.
|
||||
*/
|
||||
public function sendHeaders() {
|
||||
unset( $this->_headers['Content-Length'] );
|
||||
parent::sendHeaders();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Utility handling HTTP(s) automation issues
|
||||
*
|
||||
* @author Timely Network Inc
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http
|
||||
*/
|
||||
class Ai1ec_Http_Request {
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* @param Ai1ec_Registry_Object $registry
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( Ai1ec_Registry_Object $registry ) {
|
||||
$this->_registry = $registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for debug-checking filters. Changes debug to false for AJAX req.
|
||||
*
|
||||
* @wp_hook ai1ec_dbi_debug
|
||||
*
|
||||
* @param bool $do_debug Current debug value.
|
||||
*
|
||||
* @return bool Optionally modified `$do_debug`.
|
||||
*/
|
||||
public function debug_filter( $do_debug ) {
|
||||
if ( $this->is_ajax() ) {
|
||||
$do_debug = false;
|
||||
}
|
||||
return $do_debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we are processing AJAX request.
|
||||
*
|
||||
* @return bool True if it's an AJAX request.
|
||||
*/
|
||||
public function is_ajax() {
|
||||
if ( defined( 'DOING_AJAX' ) ) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) &&
|
||||
'XMLHttpRequest' === $_SERVER['HTTP_X_REQUESTED_WITH']
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
isset( $_GET['ai1ec_doing_ajax'] ) &&
|
||||
'true' === $_GET['ai1ec_doing_ajax']
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if ( isset( $_GET['ai1ec_js_widget'] ) ) {
|
||||
return true;
|
||||
}
|
||||
// Legacy support.
|
||||
if ( isset( $_GET['ai1ec_super_widget'] ) ) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
isset( $_GET['ai1ec_render_js'] ) ||
|
||||
isset( $_GET['ai1ec_render_css'] )
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return apply_filters( 'ai1ec_is_ajax', false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if client accepts gzip and we should compress content
|
||||
*
|
||||
* Plugin settings, client preferences and server capabilities are
|
||||
* checked to make sure we should use gzip for output compression.
|
||||
*
|
||||
* @return bool True when gzip should be used
|
||||
*/
|
||||
public function client_use_gzip() {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
|
||||
if (
|
||||
$settings->get( 'disable_gzip_compression' ) ||
|
||||
(
|
||||
isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) &&
|
||||
'identity' === $_SERVER['HTTP_ACCEPT_ENCODING'] ||
|
||||
! extension_loaded( 'zlib' )
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$zlib_output_handler = ini_get( 'zlib.output_handler' );
|
||||
if (
|
||||
in_array( 'ob_gzhandler', ob_list_handlers() ) ||
|
||||
in_array(
|
||||
strtolower( ini_get( 'zlib.output_compression' ) ),
|
||||
array( '1', 'on' )
|
||||
) ||
|
||||
! empty( $zlib_output_handler )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable `streams` transport support as necessary
|
||||
*
|
||||
* Following (`streams`) transport is disabled only when request to cron
|
||||
* dispatcher are made to make sure that requests does have no impact on
|
||||
* browsing experience - site is not slowed down, when crons are spawned
|
||||
* from within current screen session.
|
||||
*
|
||||
* @param mixed $output HTTP output
|
||||
* @param string $url Original request URL
|
||||
*
|
||||
* @return mixed Original or modified $output
|
||||
*/
|
||||
public function pre_http_request( $status, $output, $url ) {
|
||||
$cron_url = site_url( 'wp-cron.php' );
|
||||
remove_filter( 'use_streams_transport', 'ai1ec_return_false' );
|
||||
if (
|
||||
0 === strncmp( $url, $cron_url, strlen( $cron_url ) ) &&
|
||||
! function_exists( 'curl_init' )
|
||||
) {
|
||||
add_filter( 'use_streams_transport', 'ai1ec_return_false' );
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject time.ly certificate to cURL resource handle
|
||||
*
|
||||
* @param resource $curl Instance of cURL resource
|
||||
*
|
||||
* @return void Method does not return value
|
||||
*/
|
||||
public function curl_inject_certificate( $curl ) {
|
||||
// verify that the passed argument
|
||||
// is resource of type 'curl'
|
||||
if (
|
||||
is_resource( $curl ) &&
|
||||
'curl' === get_resource_type( $curl )
|
||||
) {
|
||||
// set CURLOPT_CAINFO to AI1EC_CA_ROOT_PEM
|
||||
curl_setopt( $curl, CURLOPT_CAINFO, AI1EC_CA_ROOT_PEM );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize time.ly certificate only for time.ly domain
|
||||
*
|
||||
* @param array $args Http arguments.
|
||||
* @param string $url Current URL address.
|
||||
*
|
||||
* @return void Method does not return value
|
||||
*/
|
||||
public function init_certificate( $args, $url ) {
|
||||
remove_action( 'http_api_curl', array( $this, 'curl_inject_certificate' ) );
|
||||
if ( false !== stripos( $url, '//time.ly' ) ) {
|
||||
add_action( 'http_api_curl', array( $this, 'curl_inject_certificate' ) );
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is json required for frontend rendering.
|
||||
*
|
||||
* @param string $request_format Format.
|
||||
*
|
||||
* @return bool True or false.
|
||||
*/
|
||||
public function is_json_required( $request_format, $type ) {
|
||||
$fer_list = explode( ',', AI1EC_FER_ENABLED_TEMPLATES_LIST );
|
||||
return
|
||||
'json' === $request_format &&
|
||||
in_array( strtolower( $type ), $fer_list ) &&
|
||||
$this->_registry->get(
|
||||
'model.settings'
|
||||
)->get( 'ai1ec_use_frontend_rendering' ) &&
|
||||
$this->is_ajax();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current action for bulk operations.
|
||||
*
|
||||
* @return string|null Action or null when empty.
|
||||
*/
|
||||
public function get_current_action() {
|
||||
if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) {
|
||||
return $_REQUEST['action'];
|
||||
}
|
||||
if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) {
|
||||
return $_REQUEST['action2'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract request parsing class.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Request
|
||||
*/
|
||||
abstract class Ai1ec_Abstract_Query extends Ai1ec_Base implements arrayaccess {
|
||||
/**
|
||||
* @var array Request array to parse
|
||||
*/
|
||||
protected $_request = null;
|
||||
|
||||
/**
|
||||
* @var array Parsing rules map
|
||||
*/
|
||||
protected $_rules = null;
|
||||
|
||||
/**
|
||||
* @var array Parsed values
|
||||
*/
|
||||
protected $_parsed = null;
|
||||
|
||||
/**
|
||||
* @var array Indicator - whereas parsing was finished
|
||||
*/
|
||||
protected $_ready = false;
|
||||
|
||||
/**
|
||||
* Return prefix that shall be used to access values
|
||||
*/
|
||||
abstract protected function _get_prefix( );
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Store locally copy of arguments array
|
||||
*
|
||||
* @param array $argv Arguments to be parsed [optional=null]
|
||||
*
|
||||
* @return void Constructor does not return
|
||||
*/
|
||||
public function __construct( Ai1ec_Registry_Object $registry, array $argv = NULL ) {
|
||||
parent::__construct( $registry );
|
||||
if ( NULL === $argv ) {
|
||||
$request_uri = '';
|
||||
if ( isset( $_SERVER['REQUEST_URI'] ) ) {
|
||||
$request_uri = explode( '?', $_SERVER['REQUEST_URI'] );
|
||||
$request_uri = urldecode( $request_uri[0] );
|
||||
}
|
||||
$argv = trim( $request_uri, '/' );
|
||||
if ( ( $arg_start = strpos( $argv, '/' ) ) > 0 ) {
|
||||
$argv = substr( $argv, $arg_start + 1 );
|
||||
}
|
||||
$arg_list = explode( '/', $argv );
|
||||
$argv = array();
|
||||
foreach ( $arg_list as $arg ) {
|
||||
if ( ( $colon = strpos( $arg, Ai1ec_Uri::DIRECTION_SEPARATOR ) ) > 0 ) {
|
||||
$argv[substr( $arg, 0, $colon )] = substr( $arg, $colon + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_rules = array( );
|
||||
$this->_request = $argv;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse method
|
||||
*
|
||||
* Parse request values given rules array
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public function parse() {
|
||||
if ( ! isset( $this->_request['ai1ec'] ) ) {
|
||||
$this->_request['ai1ec'] = array();
|
||||
}
|
||||
foreach ( $this->_rules as $field => $options ) {
|
||||
$value = $options['default'];
|
||||
if ( ( $ext_var = $this->_get_var( $field ) ) ) {
|
||||
$value = $this->_sane_value(
|
||||
$ext_var,
|
||||
$options
|
||||
);
|
||||
} elseif ( $options['mandatory'] ) {
|
||||
$this->_parsed = array( );
|
||||
return false;
|
||||
}
|
||||
if ( $options['is_list'] ) {
|
||||
$value = (array)$value;
|
||||
}
|
||||
$this->_parsed[$field] = $value;
|
||||
if ( ! isset( $this->_request['ai1ec'][$field] ) ) {
|
||||
$this->_request['ai1ec'][$field] = $value;
|
||||
}
|
||||
}
|
||||
$this->_ready = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parsed values map.
|
||||
*
|
||||
* @param array $name_list List of values to pull
|
||||
* If associative value is encountered - *key* is used to pull
|
||||
* request entity, and *value* to store it in returned map.
|
||||
*
|
||||
* @return array Parsed values map
|
||||
*/
|
||||
public function get_dict( array $name_list ) {
|
||||
$dictionary = array( );
|
||||
foreach ( $name_list as $alias => $name ) {
|
||||
if ( is_int( $alias ) ) {
|
||||
$alias = $name;
|
||||
}
|
||||
$value = $this->get( $name );
|
||||
if ( empty( $value ) ) {
|
||||
$value = $this->get( $alias );
|
||||
}
|
||||
$dictionary[$alias] = $value;
|
||||
}
|
||||
return $dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parsed value
|
||||
*
|
||||
* @param array $name Name of value to pull
|
||||
*
|
||||
* @return array Parsed value
|
||||
*/
|
||||
public function get( $name ) {
|
||||
if ( ! $this->_ready ) {
|
||||
return false;
|
||||
}
|
||||
if ( ! isset( $this->_parsed[$name] ) ) {
|
||||
return false;
|
||||
}
|
||||
return $this->_parsed[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the request is empry ( that means we are accessing the calendare page without parameters )
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_empty_request() {
|
||||
return empty( $this->_request );
|
||||
}
|
||||
|
||||
protected function _get_var( $name, $prefix = '' ) {
|
||||
$name = $this->_name_without_prefix( $name );
|
||||
$use_name = $prefix . $name;
|
||||
if ( isset( $this->_request[$use_name] ) ) {
|
||||
return $this->_request[$use_name];
|
||||
}
|
||||
$result = $this->_registry->get( 'http.request.wordpress-adapter' )
|
||||
->variable( $use_name );
|
||||
if ( null === $result || false === $result ) {
|
||||
$defined_prefix = $this->_get_prefix( );
|
||||
if ( '' === $prefix && $defined_prefix !== $prefix ) {
|
||||
return $this->_get_var( $name, $defined_prefix );
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function _name_without_prefix( $name ) {
|
||||
$prefix = $this->_get_prefix( );
|
||||
$length = strlen( $prefix );
|
||||
if ( 0 === strncmp( $name, $prefix, $length ) ) {
|
||||
return substr( $name, $length );
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scalar value representation
|
||||
*
|
||||
* @param array $name Name of value to pull
|
||||
*
|
||||
* @return array Parsed value converted to scalar
|
||||
*/
|
||||
public function get_scalar( $name ) {
|
||||
$value = $this->get( $name );
|
||||
if ( ! is_scalar( $value ) ) {
|
||||
$value = implode( $this->_rules[$name]['list_sep'], $value );
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overload ArrayAccess::offsetExists()
|
||||
*/
|
||||
public function offsetExists( $offset ) {
|
||||
if ( false === $this->get( $offset ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @overload ArrayAccess::offsetGet()
|
||||
*/
|
||||
public function offsetGet( $offset ) {
|
||||
return $this->get_scalar( $offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* @overload ArrayAccess::offsetSet()
|
||||
*/
|
||||
public function offsetSet( $offset, $value ) {
|
||||
// not implemented and will not be
|
||||
}
|
||||
|
||||
/**
|
||||
* @overload ArrayAccess::offsetUnset()
|
||||
*/
|
||||
public function offsetUnset( $offset ) {
|
||||
// not implemented and will not be
|
||||
}
|
||||
|
||||
/**
|
||||
* Add argument parsing rule
|
||||
*
|
||||
* @param string $field Name of field to parse
|
||||
* @param bool $mandatory Set to true for mandatory fields
|
||||
* @param string $type Type of field
|
||||
* @param mixed $default Default value to use if one is not present
|
||||
* @param string|bool $list_sep Set to list separator (i.e. ',') if it is a
|
||||
* list or false if value is not a list value.
|
||||
* For 'enum' set to array of values.
|
||||
*
|
||||
* @return bool Success
|
||||
*/
|
||||
public function add_rule(
|
||||
$field,
|
||||
$mandatory = true,
|
||||
$type = 'int',
|
||||
$default = null,
|
||||
$list_sep = false
|
||||
) {
|
||||
if ( ! is_scalar( $field ) || is_bool( $field ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( false === $this->_valid_type( $type ) ) {
|
||||
return false;
|
||||
}
|
||||
$mandatory = (bool)$mandatory;
|
||||
$is_list = false !== $list_sep && is_scalar( $list_sep );
|
||||
$field = $this->_name_without_prefix( $field );
|
||||
$prefix = $this->_get_prefix( );
|
||||
$record = compact(
|
||||
'field',
|
||||
'mandatory',
|
||||
'type',
|
||||
'default',
|
||||
'is_list',
|
||||
'list_sep'
|
||||
);
|
||||
// ? => emit notice, if field is already defined
|
||||
$this->_rules[$field] = $record;
|
||||
$this->_rules[$prefix . $field] = $record;
|
||||
$this->_ready = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* _sane_value method
|
||||
*
|
||||
* Check if given type definition is valid.
|
||||
* Return sanitizer function name (if applicable) for valid type.
|
||||
*
|
||||
* @param string $name Type name to use
|
||||
*
|
||||
* @return string|bool Name of sanitization function or false
|
||||
*/
|
||||
protected function _valid_type( $name ) {
|
||||
static $map = array(
|
||||
'int' => 'intval',
|
||||
'integer' => 'intval',
|
||||
'float' => 'floatval',
|
||||
'double' => 'floatval',
|
||||
'real' => 'floatval',
|
||||
'string' => 'strval',
|
||||
'enum' => null,
|
||||
);
|
||||
if ( !isset( $map[$name] ) ) {
|
||||
return false;
|
||||
}
|
||||
return $map[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* _sane_value method
|
||||
*
|
||||
* Parse single input value according to processing rules.
|
||||
* Relies on {@see self::_type_cast()} for value conversion.
|
||||
*
|
||||
* @param mixed $input Original request value
|
||||
* @param array $options Type definition options
|
||||
*
|
||||
* @return mixed Sanitized value
|
||||
*/
|
||||
protected function _sane_value( $input, array $options ) {
|
||||
$sane_value = null;
|
||||
if ( $options['is_list'] ) {
|
||||
$value = explode( $options['list_sep'], $input );
|
||||
$sane_value = array( );
|
||||
foreach ( $value as $element ) {
|
||||
$cast_element = $this->_type_cast( $element, $options );
|
||||
if ( ! empty( $cast_element ) ) {
|
||||
$sane_value[] = $cast_element;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$sane_value = $this->_type_cast( $input, $options );
|
||||
}
|
||||
return $sane_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* _type_cast method
|
||||
*
|
||||
* Cast value to given type.
|
||||
* Non-PHP type 'enum' is accepted
|
||||
*
|
||||
* @param mixed $value Value to cast
|
||||
* @param array $options Type definition options
|
||||
*
|
||||
* @return mixed Casted value
|
||||
*/
|
||||
protected function _type_cast( $value, array $options ) {
|
||||
if ( 'enum' === $options['type'] ) {
|
||||
if ( in_array( $value, $options['list_sep'] ) ) {
|
||||
return $value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$cast = $this->_valid_type( $options['type'] );
|
||||
$value = $cast( $value );
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Query adapter interface
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Request
|
||||
*/
|
||||
interface Ai1ec_Adapter_Query_Interface {
|
||||
|
||||
/**
|
||||
* Check if rewrite module is enabled
|
||||
*/
|
||||
public function rewrite_enabled();
|
||||
|
||||
/**
|
||||
* Register rewrite rule
|
||||
*
|
||||
* @param string $regexp Matching expression
|
||||
* @param string $landing Landing point for queries matching regexp
|
||||
* @param int $priority Rule priority (match list) [optional=NULL]
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function register_rule( $regexp, $landing, $priority = NULL );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Concrete request parsing class.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
* @instantiator new
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Request
|
||||
*/
|
||||
class Ai1ec_Request_Parser extends Ai1ec_Abstract_Query {
|
||||
|
||||
/**
|
||||
* @var int ID of page currently open
|
||||
*/
|
||||
static $current_page = NULL;
|
||||
|
||||
/**
|
||||
* set_current_page method
|
||||
*
|
||||
* Set ID of currently open page
|
||||
*
|
||||
* @param int $page_id ID of page currently open
|
||||
*
|
||||
* @return void Method does not return
|
||||
*/
|
||||
static public function set_current_page( $page_id ) {
|
||||
self::$current_page = $page_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_param function
|
||||
*
|
||||
* Tries to return the parameter from POST and GET
|
||||
* incase it is missing, default value is returned
|
||||
*
|
||||
* @param string $param Parameter to return
|
||||
* @param mixed $default Default value
|
||||
*
|
||||
* @return mixed
|
||||
**/
|
||||
static public function get_param( $param, $default='' ) {
|
||||
if ( isset( $_POST[$param] ) ) {
|
||||
return $_POST[$param];
|
||||
}
|
||||
if ( isset( $_GET[$param] ) ) {
|
||||
return $_GET[$param];
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_current_page method
|
||||
*
|
||||
* Get ID of currently open page
|
||||
*
|
||||
* @return int|NULL ID of currently open page, or NULL if none set
|
||||
*/
|
||||
static public function get_current_page() {
|
||||
return self::$current_page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate default filters for arguments parser
|
||||
*/
|
||||
public function __construct(
|
||||
Ai1ec_Registry_Object $registry,
|
||||
array $argv = null,
|
||||
$default_action = null
|
||||
) {
|
||||
parent::__construct( $registry, $argv );
|
||||
$settings_view = $this->_registry->get( 'model.settings-view' );
|
||||
$action_list = array_keys( $settings_view->get_all() );
|
||||
foreach ( $action_list as $action ) {
|
||||
$action_list[] = 'ai1ec_' . $action;
|
||||
}
|
||||
|
||||
if ( null === $default_action ) {
|
||||
$default_action = $settings_view->get_default();
|
||||
}
|
||||
|
||||
$this->add_rule(
|
||||
'action',
|
||||
false,
|
||||
'string',
|
||||
$default_action,
|
||||
$action_list
|
||||
);
|
||||
$this->add_rule( 'page_offset', false, 'int', 0, false );
|
||||
$this->add_rule( 'month_offset', false, 'int', 0, false );
|
||||
$this->add_rule( 'oneday_offset', false, 'int', 0, false );
|
||||
$this->add_rule( 'week_offset', false, 'int', 0, false );
|
||||
$this->add_rule( 'time_limit', false, 'int', 0, false );
|
||||
$this->add_rule( 'cat_ids', false, 'int', null, ',' );
|
||||
$this->add_rule( 'tag_ids', false, 'int', null, ',' );
|
||||
$this->add_rule( 'post_ids', false, 'int', null, ',' );
|
||||
$this->add_rule( 'instance_ids', false, 'int', null, ',' );
|
||||
$this->add_rule( 'auth_ids', false, 'int', null, ',' );
|
||||
$this->add_rule( 'term_ids', false, 'int', null, ',' );
|
||||
$this->add_rule( 'exact_date', false, 'string', null, false );
|
||||
// This is the type of the request: Standard, json or jsonp
|
||||
$this->add_rule( 'request_type', false, 'string', 'html', false );
|
||||
// This is the format of the request.
|
||||
$this->add_rule( 'request_format',false, 'string', 'html', false );
|
||||
// The callback function for jsonp calls
|
||||
$this->add_rule( 'callback', false, 'string', null, false );
|
||||
// Whether to include navigation controls
|
||||
$this->add_rule( 'no_navigation' ,false, 'string', false, false );
|
||||
// whether to display the filter bar in the super widget
|
||||
$this->add_rule( 'display_filters' ,false, 'string', false, false );
|
||||
$this->add_rule( 'applying_filters' ,false, 'string', false, false );
|
||||
$this->add_rule( 'shortcode' ,false, 'string', false, false );
|
||||
$this->add_rule( 'events_limit', false, 'int', null, false );
|
||||
do_action( 'ai1ec_request_parser_rules_added', $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query argument name prefix.
|
||||
*
|
||||
* Inherited from parent class. Method is used to detect query name
|
||||
* prefix, that is used to "namespace" own (private) query variables.
|
||||
*
|
||||
* @return string Query prefix 'ai1ec_'
|
||||
*/
|
||||
protected function _get_prefix() {
|
||||
return 'ai1ec_';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wordpress query adapter
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Request
|
||||
*/
|
||||
class Ai1ec_Adapter_Query_Wordpress implements Ai1ec_Adapter_Query_Interface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var WP_Query Instance of WP_Query object
|
||||
*/
|
||||
protected $_query = null;
|
||||
|
||||
/**
|
||||
* @var WP_Rewrite Instance of WP_Rewrite object
|
||||
*/
|
||||
protected $_rewrite = null;
|
||||
|
||||
/**
|
||||
* @var array List of parsed query variables
|
||||
*/
|
||||
protected $_query_vars = array();
|
||||
|
||||
/**
|
||||
* Initiate object entities
|
||||
*
|
||||
* @param object $query_object Instance of query object [optional=WP_Query]
|
||||
* @param object $rewrite_object Instance of query object [optional=WP_Rewrite]
|
||||
*
|
||||
* @return void Constructor does not return
|
||||
*/
|
||||
public function __construct(
|
||||
$query_object = null,
|
||||
$rewrite_object = null
|
||||
) {
|
||||
if ( null === $query_object ) {
|
||||
global $wp_query;
|
||||
$query_object = $wp_query;
|
||||
}
|
||||
$this->_query = $query_object;
|
||||
if ( null === $rewrite_object ) {
|
||||
global $wp_rewrite;
|
||||
$rewrite_object = $wp_rewrite;
|
||||
}
|
||||
$this->_rewrite = $rewrite_object;
|
||||
$this->init_vars();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query variable setter/getter
|
||||
*
|
||||
* @param string $name Name of variable to query
|
||||
* @param mixed $value Value to set [optional=null/act as getter]
|
||||
*
|
||||
* @return mixed Variable, null if not present, true in setter mode
|
||||
*/
|
||||
public function variable( $name, $value = null ) {
|
||||
if ( null !== $value ) {
|
||||
$this->_query_vars[$name] = $value;
|
||||
return true;
|
||||
}
|
||||
if ( ! isset( $this->_query_vars[$name] ) ) {
|
||||
return null;
|
||||
}
|
||||
return $this->_query_vars[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate (populate) query variables list. Two different url structures are supported.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public function init_vars( $query = null ) {
|
||||
foreach ( $_REQUEST as $key => $value ) {
|
||||
$this->variable( $key, $value );
|
||||
}
|
||||
if ( null === $query ) {
|
||||
$query = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
|
||||
}
|
||||
|
||||
$particles = explode( '/', trim( $query, '/' ) );
|
||||
$imported = 0;
|
||||
foreach ( $particles as $element ) {
|
||||
if ( $this->_add_serialized_var( $element ) ) {
|
||||
++$imported;
|
||||
}
|
||||
}
|
||||
if ( isset( $_REQUEST['ai1ec'] ) ) {
|
||||
$particles = explode( '|', trim( $_REQUEST['ai1ec'], '|' ) );
|
||||
foreach ( $particles as $element ) {
|
||||
if ( $this->_add_serialized_var( $element ) ) {
|
||||
++$imported;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $imported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if rewrite module is enabled
|
||||
*/
|
||||
public function rewrite_enabled() {
|
||||
return $this->_rewrite->using_mod_rewrite_permalinks();
|
||||
}
|
||||
|
||||
/**
|
||||
* register_rule method
|
||||
*
|
||||
* Register rewrite rule with framework
|
||||
*
|
||||
* @param string $regexp Expression to register
|
||||
* @param string $landing URL to be executed on match
|
||||
* @param int $priority Numeric rule priority - higher means sooner check
|
||||
*
|
||||
* @return string Regexp rule registered with framework
|
||||
*/
|
||||
public function register_rule( $regexp, $landing, $priority = NULL ) {
|
||||
if ( NULL === $priority ) {
|
||||
$priority = 1;
|
||||
}
|
||||
$priority = ( $priority > 0 ) ? 'top' : 'bottom';
|
||||
$regexp = $this->_inject_route_groups( $regexp );
|
||||
$existing = $this->_rewrite->wp_rewrite_rules();
|
||||
if ( ! isset( $existing[$regexp] ) ) {
|
||||
$this->_rewrite->add_rule(
|
||||
$regexp,
|
||||
$landing,
|
||||
$priority
|
||||
);
|
||||
$this->_rewrite->flush_rules();
|
||||
}
|
||||
return $regexp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add serialized (key:value) value to query arguments list
|
||||
*/
|
||||
protected function _add_serialized_var( $element ) {
|
||||
if ( false === strpos( $element, Ai1ec_Uri::DIRECTION_SEPARATOR ) ) {
|
||||
return false;
|
||||
}
|
||||
list( $key, $value ) = explode( Ai1ec_Uri::DIRECTION_SEPARATOR, $element, 2 );
|
||||
$this->variable( $key, $value );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust regexp groupping identifiers using WP_Rewrite object
|
||||
*/
|
||||
protected function _inject_route_groups( $query ) {
|
||||
$elements = preg_split(
|
||||
'/\$(\d+)/',
|
||||
$query,
|
||||
null,
|
||||
PREG_SPLIT_DELIM_CAPTURE
|
||||
);
|
||||
$result = '';
|
||||
foreach ( $elements as $key => $value ) {
|
||||
if ( $key % 2 == 1 ) {
|
||||
$value = $this->_rewrite->preg_index($value);
|
||||
}
|
||||
$result .= $value;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class to group HTTP response related functionality
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response
|
||||
*/
|
||||
class Ai1ec_Http_Response_Helper {
|
||||
|
||||
/**
|
||||
* Perform redirect to desired location and stop script execution after that
|
||||
*
|
||||
* When debug mode is activated redirect doesn't happen but instead link
|
||||
* is outputted to screen, to allow developer to tamper with the flow, debug
|
||||
* it and make changes as desired.
|
||||
*
|
||||
* @param string $location Location to redirect user to
|
||||
* @param int $code HTTP response code to use in redirects
|
||||
*
|
||||
* @uses wp_redirect To create actual headers.
|
||||
*
|
||||
* @return int|NULL Method does call {@see self::stop()} to halt further
|
||||
* script execution unless mocked
|
||||
*/
|
||||
public static function redirect( $location, $code = 302 ) {
|
||||
header( 'Location: ' . $location, true, $code );
|
||||
return self::stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mockable method to halt script execution
|
||||
*
|
||||
* @param int $code Code to be used in `exit` statement
|
||||
*
|
||||
* @return void Method does not return
|
||||
*/
|
||||
public static function stop( $code = 0 ) {
|
||||
exit( $code );
|
||||
}
|
||||
|
||||
/**
|
||||
* ai1ec_utf8 function
|
||||
*
|
||||
* Encode value as safe UTF8 - discarding unrecognized characters.
|
||||
* NOTE: objects will be cast as array.
|
||||
*
|
||||
* @uses iconv To change encoding
|
||||
* @uses mb_convert_encoding To change encoding if `iconv` is not available
|
||||
*
|
||||
* @param mixed $input Value to encode
|
||||
*
|
||||
* @return mixed UTF8 encoded value
|
||||
*
|
||||
* @throws Exception If no trans-coding method is available
|
||||
*/
|
||||
public static function utf8( $input ) {
|
||||
if ( NULL === $input ) {
|
||||
return NULL;
|
||||
}
|
||||
if ( is_scalar( $input ) ) {
|
||||
if ( function_exists( 'iconv' ) ) {
|
||||
return iconv( 'UTF-8', 'UTF-8//IGNORE', $input );
|
||||
}
|
||||
if ( function_exists( 'mb_convert_encoding' ) ) {
|
||||
return mb_convert_encoding( $input, 'UTF-8' );
|
||||
}
|
||||
throw new Exception(
|
||||
'Either `iconv` or `mb_convert_encoding` must be available.'
|
||||
);
|
||||
}
|
||||
if ( ! is_array( $input ) ) {
|
||||
$input = (array)$input;
|
||||
}
|
||||
return array_map( array( __CLASS__, 'utf8' ), $input );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the protocla from the url
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function remove_protocols( $url ) {
|
||||
$disallowed = array( 'http:', 'https:' );
|
||||
foreach ( $disallowed as $d ) {
|
||||
if ( strpos( $url, $d ) === 0 ) {
|
||||
return str_replace( $d, '', $url );
|
||||
}
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract strategy class to render the Request.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render
|
||||
*/
|
||||
abstract class Ai1ec_Http_Response_Render_Strategy extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Dump output buffers before starting output
|
||||
*
|
||||
* @return bool True unless an error occurs
|
||||
*/
|
||||
protected function _dump_buffers() {
|
||||
$this->_registry->get( 'dbi.dbi' )->disable_debug();
|
||||
|
||||
|
||||
return $this
|
||||
->_registry
|
||||
->get( 'compatibility.ob' )
|
||||
->end_clean_all();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the output.
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
abstract public function render( array $params );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Render the request as csv
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Csv extends Ai1ec_Http_Response_Render_Strategy {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Http_Response_Render_Strategy::render()
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
$this->_dump_buffers();
|
||||
|
||||
$now = gmdate( 'D, d M Y H:i:s' );
|
||||
$filename = $params['filename'];
|
||||
|
||||
header( 'Expires: Tue, 03 Jul 2001 06:00:00 GMT' );
|
||||
header( 'Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate' );
|
||||
header( 'Last-Modified: ' . $now . ' GMT' );
|
||||
|
||||
// force download
|
||||
header( 'Content-Type: application/force-download' );
|
||||
header( 'Content-Type: application/octet-stream' );
|
||||
header( 'Content-Type: application/download' );
|
||||
|
||||
// disposition / encoding on response body
|
||||
header( 'Content-Disposition: attachment;filename="' . addcslashes(
|
||||
$filename, '"' ) . '"' );
|
||||
header( 'Content-Transfer-Encoding: binary' );
|
||||
|
||||
$columns = $params['columns'];
|
||||
for ( $i = 0; $i < count( $columns ); $i++ ) {
|
||||
if ( $i > 0 ) {
|
||||
echo( ',' );
|
||||
}
|
||||
echo( $columns[$i] );
|
||||
}
|
||||
echo( "\n" );
|
||||
|
||||
$data = $params['data'];
|
||||
for ( $i = 0; $i < count( $data ); $i++ ) {
|
||||
$row = $data[$i];
|
||||
for ( $j = 0; $j < count( $row ); $j++ ) {
|
||||
if ( $j > 0 ) {
|
||||
echo( ',' );
|
||||
}
|
||||
echo( $row[$j] );
|
||||
}
|
||||
echo( "\n" );
|
||||
}
|
||||
|
||||
return Ai1ec_Http_Response_Helper::stop( 0 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/**
|
||||
* Render the request as html.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Html extends Ai1ec_Http_Response_Render_Strategy {
|
||||
|
||||
/**
|
||||
* Twig page content placeholder.
|
||||
*/
|
||||
const CALENDAR_PLACEHOLDER = '<!-- AI1EC_PAGE_CONTENT_PLACEHOLDER -->';
|
||||
|
||||
/**
|
||||
* @var string the event html.
|
||||
*/
|
||||
protected $_html;
|
||||
|
||||
/**
|
||||
* @var string The html for the footer of the event.
|
||||
*/
|
||||
protected $_html_footer = '';
|
||||
|
||||
/**
|
||||
* Caller identifier. Just for paranoid check in append_content method.
|
||||
* Expected 'calendar' or none.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_caller = '';
|
||||
|
||||
/**
|
||||
* Registers proper filters for content modifications.
|
||||
*
|
||||
* @param array $params Function params.
|
||||
*
|
||||
* @return void Method does not return.
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
$this->_html = $params['data'];
|
||||
if ( isset( $params['caller'] ) ) {
|
||||
$this->_caller = $params['caller'];
|
||||
}
|
||||
if ( isset( $params['footer'] ) ) {
|
||||
$this->_html_footer = $params['footer'];
|
||||
}
|
||||
if ( isset( $params['is_event'] ) ) {
|
||||
// Filter event post content, in single- and multi-post views
|
||||
add_filter( 'the_content', array( $this, 'event_content' ), PHP_INT_MAX - 1 );
|
||||
return;
|
||||
}
|
||||
// Replace page content - make sure it happens at (almost) the very end of
|
||||
add_filter( 'the_content', array( $this, 'append_content' ), PHP_INT_MAX - 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Append locally generated content to normal page content. By default,
|
||||
* first checks if we are in The Loop before outputting to prevent multiple
|
||||
* calendar display - unless setting is turned on to skip this check.
|
||||
* We should not append full calendar body to single event content as it
|
||||
* leads to "calendar" nesting if default calendar page contains calendar
|
||||
* shortcode.
|
||||
*
|
||||
* @param string $content Post/Page content
|
||||
* @return string Modified Post/Page content
|
||||
*/
|
||||
public function append_content( $content ) {
|
||||
if (
|
||||
'calendar' === $this->_caller &&
|
||||
! $this->_registry->get( 'calendar.state' )->append_content()
|
||||
) {
|
||||
return $content;
|
||||
}
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
|
||||
// Include any admin-provided page content in the placeholder specified in
|
||||
// the calendar theme template.
|
||||
if ( $settings->get( 'skip_in_the_loop_check' ) || in_the_loop() ) {
|
||||
$content = str_replace(
|
||||
self::CALENDAR_PLACEHOLDER,
|
||||
$content,
|
||||
$this->_html
|
||||
);
|
||||
$content .= $this->_html_footer;
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* event_content function
|
||||
*
|
||||
* Filter event post content by inserting relevant details of the event
|
||||
* alongside the regular post content.
|
||||
*
|
||||
* @param string $content Post/Page content
|
||||
*
|
||||
* @return string Post/Page content
|
||||
**/
|
||||
public function event_content( $content ) {
|
||||
if ( ! $this->_registry->get( 'calendar.state' )->append_content() ) {
|
||||
$content = '';
|
||||
}
|
||||
$to_return = $this->_html . $content;
|
||||
if ( isset( $this->_html_footer ) ) {
|
||||
$to_return .= $this->_html_footer;
|
||||
}
|
||||
// Pass the orginal content to the filter so that it can be modified
|
||||
return apply_filters(
|
||||
'ai1ec_event_content',
|
||||
$to_return,
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Render the request as ical.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Ical extends Ai1ec_Http_Response_Render_Strategy {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Http_Response_Render_Strategy::render()
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
$this->_dump_buffers();
|
||||
header( 'Content-type: text/calendar; charset=utf-8' );
|
||||
echo $params['data'];
|
||||
return Ai1ec_Http_Response_Helper::stop( 0 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Render the request as json.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Json extends Ai1ec_Render_Strategy_Jsonp {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Http_Response_Render_Strategy::render()
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
$params['callback'] = '';
|
||||
return parent::render( $params );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Render the request as jsonp.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Jsonp extends Ai1ec_Http_Response_Render_Strategy {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Http_Response_Render_Strategy::render()
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
$this->_dump_buffers();
|
||||
header( 'HTTP/1.1 200 OK' );
|
||||
header( 'Content-Type: application/json; charset=UTF-8' );
|
||||
$data = Ai1ec_Http_Response_Helper::utf8( $params['data'] );
|
||||
$output = json_encode( $data );
|
||||
if ( ! empty( $params['callback'] ) ) {
|
||||
$output = $params['callback'] . '(' . $output . ')';
|
||||
} else if ( isset( $_GET['callback'] ) ) {
|
||||
$output = $_GET['callback'] . '(' . $output . ')';
|
||||
}
|
||||
|
||||
echo $output;
|
||||
return Ai1ec_Http_Response_Helper::stop( 0 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Render the request as ical.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Redirect extends Ai1ec_Http_Response_Render_Strategy {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Http_Response_Render_Strategy::render()
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
Ai1ec_Wp_Uri_Helper::local_redirect(
|
||||
$params['url'],
|
||||
$params['query_args']
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Do not render anything.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Void extends Ai1ec_Http_Response_Render_Strategy {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Http_Response_Render_Strategy::render()
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Render the request as xcal.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.3
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Xcal extends Ai1ec_Http_Response_Render_Strategy {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Http_Response_Render_Strategy::render()
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
$this->_dump_buffers();
|
||||
header( 'Content-Type: application/force-download; name="calendar.xml"' );
|
||||
header( 'Content-type: text/xml' );
|
||||
header( 'Content-Transfer-Encoding: binary' );
|
||||
header( 'Content-Disposition: attachment; filename="calendar.xml"' );
|
||||
header( 'Expires: 0' );
|
||||
header( 'Cache-Control: no-cache, must-revalidate' );
|
||||
header( 'Pragma: no-cache' );
|
||||
echo $params['data'];
|
||||
return Ai1ec_Http_Response_Helper::stop( 0 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Render the request as xml.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.Http.Response.Render.Strategy
|
||||
*/
|
||||
class Ai1ec_Render_Strategy_Xml extends Ai1ec_Http_Response_Render_Strategy {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Http_Response_Render_Strategy::render()
|
||||
*/
|
||||
public function render( array $params ) {
|
||||
$this->_dump_buffers();
|
||||
header( 'HTTP/1.1 200 OK' );
|
||||
header( 'Content-Type: text/xml; charset=UTF-8' );
|
||||
$data = Ai1ec_Http_Response_Helper::utf8( $params['data'] );
|
||||
$output = Ai1ec_XML_Builder::serialize_to_xml( $data );
|
||||
echo $output;
|
||||
return Ai1ec_Http_Response_Helper::stop( 0 );
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user