Add upstream plugins

Signed-off-by: Adrian Nöthlich <git@promasu.tech>
This commit is contained in:
2019-10-25 22:42:20 +02:00
parent 5d3c2ec184
commit 290736650a
1186 changed files with 302577 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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 );
}

View File

@@ -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_';
}
}

View File

@@ -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;
}
}