From dcfb9b056631ab8a5f494b50556fb8c8b1e573c7 Mon Sep 17 00:00:00 2001 From: nikitasinelnikov Date: Wed, 10 Apr 2019 15:00:13 +0300 Subject: [PATCH] - added REST API version; - avoid the conflicts (added prefixes for query vars); --- includes/admin/core/class-admin-settings.php | 10 + includes/class-config.php | 3 +- includes/class-init.php | 15 +- includes/core/class-rest-api.php | 1160 ------------------ includes/core/rest/class-api-v1.php | 541 ++++++++ includes/core/rest/class-api-v2.php | 540 ++++++++ includes/core/rest/class-api.php | 615 ++++++++++ 7 files changed, 1721 insertions(+), 1163 deletions(-) delete mode 100644 includes/core/class-rest-api.php create mode 100644 includes/core/rest/class-api-v1.php create mode 100644 includes/core/rest/class-api-v2.php create mode 100644 includes/core/rest/class-api.php diff --git a/includes/admin/core/class-admin-settings.php b/includes/admin/core/class-admin-settings.php index 839c0cb4..187f5d8c 100644 --- a/includes/admin/core/class-admin-settings.php +++ b/includes/admin/core/class-admin-settings.php @@ -1073,6 +1073,16 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { 'label' => __( 'Enable Gutenberg Blocks', 'ultimate-member' ), 'tooltip' => __( 'Check this box if you would like to use Ultimate Member blocks in Gutenberg editor. Important some themes have the conflicts with Gutenberg editor.', 'ultimate-member' ), ), + array( + 'id' => 'rest_api_version', + 'type' => 'select', + 'label' => __( 'REST API version','ultimate-member' ), + 'tooltip' => __( 'This controls the REST API version, we recommend to use the last version', 'ultimate-member' ), + 'options' => array( + '1.0' => __( '1.0 version', 'ultimate-member' ), + '2.0' => __( '2.0 version', 'ultimate-member' ), + ), + ), array( 'id' => 'uninstall_on_delete', 'type' => 'checkbox', diff --git a/includes/class-config.php b/includes/class-config.php index b2daadb1..4e54eef5 100644 --- a/includes/class-config.php +++ b/includes/class-config.php @@ -535,7 +535,8 @@ if ( ! class_exists( 'um\Config' ) ) { 'profile_photo_max_size' => 999999999, 'cover_photo_max_size' => 999999999, 'custom_roles_increment' => 1, - 'um_profile_object_cache_stop' => 0 + 'um_profile_object_cache_stop' => 0, + 'rest_api_version' => '2.0' ); $tabs = UM()->profile()->tabs_primary(); diff --git a/includes/class-init.php b/includes/class-init.php index 556812ed..d142ce45 100644 --- a/includes/class-init.php +++ b/includes/class-init.php @@ -469,6 +469,8 @@ if ( ! class_exists( 'UM' ) ) { if ( ! get_option( 'show_avatars' ) ) { update_option( 'show_avatars', 1 ); } + } else { + UM()->options()->update( 'rest_api_version', '1.0' ); } if ( $version != ultimatemember_version ) { @@ -937,11 +939,20 @@ if ( ! class_exists( 'UM' ) ) { /** * @since 2.0 * - * @return um\core\REST_API + * @return um\core\rest\API_v1|um\core\rest\API_v2 */ function rest_api() { + + $api_version = $this->options()->get( 'rest_api_version' ); + if ( empty( $this->classes['rest_api'] ) ) { - $this->classes['rest_api'] = new um\core\REST_API(); + if ( '1.0' === $api_version ) { + $this->classes['rest_api'] = new um\core\rest\API_v1(); + } elseif ( '2.0' === $api_version ) { + $this->classes['rest_api'] = new um\core\rest\API_v2(); + } else { + $this->classes['rest_api'] = new um\core\rest\API_v1(); + } } return $this->classes['rest_api']; diff --git a/includes/core/class-rest-api.php b/includes/core/class-rest-api.php deleted file mode 100644 index 8bf1f537..00000000 --- a/includes/core/class-rest-api.php +++ /dev/null @@ -1,1160 +0,0 @@ -pretty_print = defined( 'JSON_PRETTY_PRINT' ) ? JSON_PRETTY_PRINT : null; - - /** - * UM hook - * - * @type filter - * @title um_api_log_requests - * @description Allow API request logging to be turned off - * @input_vars - * [{"var":"$allow_log","type":"bool","desc":"Enable api logs"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $this->log_requests = apply_filters( 'um_api_log_requests', $this->log_requests ); - } - - - /** - * Registers a new rewrite endpoint for accessing the API - * - * @param $rewrite_rules - */ - public function add_endpoint( $rewrite_rules ) { - add_rewrite_endpoint( 'um-api', EP_ALL ); - } - - - /** - * Registers query vars for API access - * - * @param $vars - * - * @return array - */ - public function query_vars( $vars ) { - - $vars[] = 'key'; - $vars[] = 'token'; - $vars[] = 'format'; - $vars[] = 'query'; - $vars[] = 'type'; - $vars[] = 'data'; - $vars[] = 'fields'; - $vars[] = 'value'; - $vars[] = 'number'; - $vars[] = 'id'; - $vars[] = 'email'; - $vars[] = 'orderby'; - $vars[] = 'order'; - $vars[] = 'include'; - $vars[] = 'exclude'; - - $this->vars = $vars; - - return $vars; - } - - - /** - * Validate the API request - */ - private function validate_request() { - global $wp_query; - - $this->override = false; - - // Make sure we have both user and api key - if ( ! empty( $wp_query->query_vars['um-api'] ) ) { - - if ( empty( $wp_query->query_vars['token'] ) || empty( $wp_query->query_vars['key'] ) ) - $this->missing_auth(); - - // Retrieve the user by public API key and ensure they exist - if ( ! ( $user = $this->get_user( $wp_query->query_vars['key'] ) ) ) : - $this->invalid_key(); - else : - $token = urldecode( $wp_query->query_vars['token'] ); - $secret = get_user_meta( $user, 'um_user_secret_key', true ); - $public = urldecode( $wp_query->query_vars['key'] ); - - if ( hash_equals( md5( $secret . $public ), $token ) ) - $this->is_valid_request = true; - else - $this->invalid_auth(); - endif; - } - } - - - /** - * Retrieve the user ID based on the public key provided - * - * @param string $key - * - * @return bool|mixed|null|string - */ - public function get_user( $key = '' ) { - global $wpdb, $wp_query; - - if( empty( $key ) ) - $key = urldecode( $wp_query->query_vars['key'] ); - - if ( empty( $key ) ) { - return false; - } - - $user = get_transient( md5( 'um_api_user_' . $key ) ); - - if ( false === $user ) { - $user = $wpdb->get_var( $wpdb->prepare( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'um_user_public_key' AND meta_value = %s LIMIT 1", $key ) ); - set_transient( md5( 'um_api_user_' . $key ) , $user, DAY_IN_SECONDS ); - } - - if ( $user != NULL ) { - $this->user_id = $user; - return $user; - } - - return false; - } - - - /** - * Displays a missing authentication error if all the parameters aren't - * provided - */ - private function missing_auth() { - $error = array(); - $error['error'] = __( 'You must specify both a token and API key!', 'ultimate-member' ); - - $this->data = $error; - $this->output( 401 ); - } - - - /** - * Displays an authentication failed error if the user failed to provide valid credentials - */ - private function invalid_auth() { - $error = array(); - $error['error'] = __( 'Your request could not be authenticated', 'ultimate-member' ); - - $this->data = $error; - $this->output( 401 ); - } - - - /** - * Displays an invalid API key error if the API key provided couldn't be validated - */ - private function invalid_key() { - $error = array(); - $error['error'] = __( 'Invalid API key', 'ultimate-member' ); - - $this->data = $error; - $this->output( 401 ); - } - - - /** - * Listens for the API and then processes the API requests - */ - public function process_query() { - global $wp_query; - - // Check for um-api var. Get out if not present - if ( ! isset( $wp_query->query_vars['um-api'] ) ) - return; - - // Check for a valid user and set errors if necessary - $this->validate_request(); - - // Only proceed if no errors have been noted - if( ! $this->is_valid_request ) - return; - - if( ! defined( 'UM_DOING_API' ) ) { - define( 'UM_DOING_API', true ); - } - - // Determine the kind of query - $args = array(); - $query_mode = $this->get_query_mode(); - foreach( $this->vars as $k ) { - $args[ $k ] = isset( $wp_query->query_vars[ $k ] ) ? $wp_query->query_vars[ $k ] : null; - } - - $data = array(); - - switch( $query_mode ) { - - case 'get.stats': - $data = $this->get_stats( $args ); - break; - - case 'get.users': - $data = $this->get_users( $args ); - break; - - case 'get.user': - $data = $this->get_auser( $args ); - break; - - case 'update.user': - $data = $this->update_user( $args ); - break; - - case 'delete.user': - $data = $this->delete_user( $args ); - break; - - default: - /** - * UM hook - * - * @type filter - * @title um_rest_query_mode - * @description Change query attributes - * @input_vars - * [{"var":"$data","type":"array","desc":"Query Data"}, - * {"var":"$query_mode","type":"string","desc":"Query Mode"}, - * {"var":"$args","type":"array","desc":"Query Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $data = apply_filters( 'um_rest_query_mode', $data, $query_mode, $args ); - } - - /** - * UM hook - * - * @type filter - * @title um_api_output_data - * @description Change output data for Rest API call - * @input_vars - * [{"var":"$data","type":"array","desc":"Output Data"}, - * {"var":"$query_mode","type":"string","desc":"Query Mode"}, - * {"var":"$api_class","type":"REST_API","desc":"REST_API instance"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $this->data = apply_filters( 'um_api_output_data', $data, $query_mode, $this ); - - // Log this API request, if enabled. We log it here because we have access to errors. - $this->log_request( $this->data ); - - // Send out data to the output function - $this->output(); - } - - - /** - * Get some stats - * - * @param $args - * - * @return array|mixed|void - */ - public function get_stats( $args ) { - global $wpdb; - extract( $args ); - - $response = array(); - - $query = "SELECT COUNT(*) FROM {$wpdb->prefix}users"; - $count = absint( $wpdb->get_var($query) ); - $response['stats']['total_users'] = $count; - - $pending = UM()->user()->get_pending_users_count(); - $response['stats']['pending_users'] = absint( $pending ); - - /** - * UM hook - * - * @type filter - * @title um_rest_api_get_stats - * @description Change output data for Rest API get stats call - * @input_vars - * [{"var":"$response","type":"array","desc":"Output Data"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $response = apply_filters( 'um_rest_api_get_stats', $response ); - return $response; - } - - - /** - * Update user API query - * - * @param $args - * - * @return array - */ - public function update_user( $args ) { - extract( $args ); - - $response = array(); - $error = array(); - - if ( !$id ) { - $error['error'] = __('You must provide a user ID','ultimate-member'); - return $error; - } - - if ( !$data ) { - $error['error'] = __('You need to provide data to update','ultimate-member'); - return $error; - } - - um_fetch_user( $id ); - - switch ( $data ) { - case 'status': - UM()->user()->set_status( $value ); - $response['success'] = __('User status has been changed.','ultimate-member'); - break; - case 'role': - $wp_user_object = new \WP_User( $id ); - $old_roles = $wp_user_object->roles; - $wp_user_object->set_role( $value ); - - /** - * UM hook - * - * @type action - * @title um_after_member_role_upgrade - * @description Action after user role was changed - * @input_vars - * [{"var":"$new_roles","type":"array","desc":"New User Roles"}, - * {"var":"$old_roles","type":"array","desc":"Old roles"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_after_member_role_upgrade', 'function_name', 10, 2 ); - * @example - * - */ - do_action( 'um_after_member_role_upgrade', array( $value ), $old_roles, $id ); - - $response['success'] = __( 'User role has been changed.', 'ultimate-member' ); - break; - default: - update_user_meta( $id, $data, esc_attr( $value ) ); - $response['success'] = __('User meta has been changed.','ultimate-member'); - break; - } - - return $response; - } - - - /** - * Process Get users API Request - * - * @param $args - * - * @return array - */ - public function get_users( $args ) { - extract( $args ); - - $response = array(); - $error = array(); - - if ( !$number ) - $number = 10; - - if ( !$orderby ) - $orderby = 'user_registered'; - - if ( !$order ) - $order = 'desc'; - - $loop_a = array('number' => $number, 'orderby' => $orderby, 'order' => $order ); - - if ( $include ) { - $include = explode(',', $include ); - $loop_a['include'] = $include; - } - - if ( $exclude ) { - $exclude = explode(',', $exclude ); - $loop_a['exclude'] = $exclude; - } - - $loop = get_users( $loop_a ); - - foreach( $loop as $user ) { - - unset( $user->data->user_status ); - unset( $user->data->user_activation_key ); - unset( $user->data->user_pass ); - - um_fetch_user( $user->ID ); - - foreach( $user as $key => $val ) { - if ( $key != 'data' ) continue; - if ( $key == 'data' ) { - $key = 'profile'; - $val->roles = $user->roles; - $val->first_name = um_user('first_name'); - $val->last_name = um_user('last_name'); - $val->account_status = um_user('account_status'); - $val->profile_pic_original = um_get_user_avatar_url('', 'original'); - $val->profile_pic_normal = um_get_user_avatar_url('', 200); - $val->profile_pic_small = um_get_user_avatar_url('', 40); - $val->cover_photo = $this->getsrc( um_user('cover_photo', 1000) ); - - /** - * UM hook - * - * @type filter - * @title um_rest_userdata - * @description Change output data for Rest API userdata call - * @input_vars - * [{"var":"$value","type":"array","desc":"Output Data"}, - * {"var":"$user_id","type":"string","desc":"User ID"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $val = apply_filters( 'um_rest_userdata', $val, $user->ID ); - } - $response[ $user->ID ] = $val; - } - - } - - return $response; - } - - - /** - * Process delete user via API - * - * @param $args - * - * @return array - */ - public function delete_user( $args ) { - extract( $args ); - - $response = array(); - $error = array(); - - if ( !isset( $id ) ) { - $error['error'] = __('You must provide a user ID','ultimate-member'); - return $error; - } - - $user = get_userdata( $id ); - if ( !$user ) { - $error['error'] = __('Invalid user specified','ultimate-member'); - return $error; - } - - um_fetch_user( $id ); - UM()->user()->delete(); - - $response['success'] = __('User has been successfully deleted.','ultimate-member'); - - return $response; - } - - - /** - * Process Get user API Request - * - * @param $args - * - * @return array|mixed|void - */ - public function get_auser( $args ) { - extract( $args ); - - $response = array(); - $error = array(); - - if ( !isset( $id ) ) { - $error['error'] = __('You must provide a user ID','ultimate-member'); - return $error; - } - - $user = get_userdata( $id ); - if ( ! $user ) { - $error['error'] = __('Invalid user specified','ultimate-member'); - return $error; - } - - unset( $user->data->user_status ); - unset( $user->data->user_activation_key ); - unset( $user->data->user_pass ); - - um_fetch_user( $user->ID ); - - if ( isset( $fields ) && $fields ) { - $fields = explode(',', $fields ); - $response['ID'] = $user->ID; - $response['username'] = $user->user_login; - foreach ( $fields as $field ) { - - switch( $field ) { - - default: - $response[ $field ] = ( um_profile( $field ) ) ? um_profile( $field ) : ''; - - /** - * UM hook - * - * @type filter - * @title um_rest_get_auser - * @description Change output data for Rest API user authentification call - * @input_vars - * [{"var":"$response","type":"array","desc":"Output Data"}, - * {"var":"$field","type":"string","desc":"Field Key"}, - * {"var":"$user_id","type":"int","desc":"User ID"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $response = apply_filters( 'um_rest_get_auser', $response, $field, $user->ID ); - break; - - case 'cover_photo': - $response['cover_photo'] = $this->getsrc( um_user('cover_photo', 1000) ); - break; - - case 'profile_pic': - $response['profile_pic_original'] = um_get_user_avatar_url('', 'original'); - $response['profile_pic_normal'] = um_get_user_avatar_url('', 200); - $response['profile_pic_small'] = um_get_user_avatar_url('', 40); - break; - - case 'status': - $response['status'] = um_user('account_status'); - break; - - case 'role': - //get priority role here - $response['role'] = um_user( 'role' ); - break; - - case 'email': - case 'user_email': - $response['email'] = um_user('user_email'); - break; - - } - - } - } else { - - foreach( $user as $key => $val ) { - if ( $key != 'data' ) continue; - if ( $key == 'data' ) { - $key = 'profile'; - $val->roles = $user->roles; - $val->first_name = um_user('first_name'); - $val->last_name = um_user('last_name'); - $val->account_status = um_user('account_status'); - $val->profile_pic_original = um_get_user_avatar_url('', 'original'); - $val->profile_pic_normal = um_get_user_avatar_url('', 200); - $val->profile_pic_small = um_get_user_avatar_url('', 40); - $val->cover_photo = $this->getsrc( um_user('cover_photo', 1000) ); - - /** - * UM hook - * - * @type filter - * @title um_rest_userdata - * @description Change output data for Rest API userdata call - * @input_vars - * [{"var":"$value","type":"array","desc":"Output Data"}, - * {"var":"$user_id","type":"string","desc":"User ID"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $val = apply_filters( 'um_rest_userdata', $val, $user->ID ); - } - $response = $val; - } - - } - - return $response; - } - - - /** - * Get source - * - * @param $image - * - * @return string - */ - public function getsrc( $image ) { - if (preg_match('/ - * @example - * - */ - $accepted = apply_filters( 'um_api_valid_query_modes', array( - 'get.users', - 'get.user', - 'update.user', - 'delete.user', - 'get.following', - 'get.followers', - 'get.stats', - ) ); - - $query = isset( $wp_query->query_vars['um-api'] ) ? $wp_query->query_vars['um-api'] : null; - $error = array(); - // Make sure our query is valid - if ( ! in_array( $query, $accepted ) ) { - $error['error'] = __( 'Invalid query!', 'ultimate-member' ); - - $this->data = $error; - $this->output(); - } - - return $query; - } - - - /** - * Get page number - */ - public function get_paged() { - global $wp_query; - - return isset( $wp_query->query_vars['page'] ) ? $wp_query->query_vars['page'] : 1; - } - - - /** - * Retrieve the output format - */ - public function get_output_format() { - global $wp_query; - - $format = isset( $wp_query->query_vars['format'] ) ? $wp_query->query_vars['format'] : 'json'; - - /** - * UM hook - * - * @type filter - * @title um_api_output_format - * @description UM Rest API output format - * @input_vars - * [{"var":"$format","type":"string","desc":"Format"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - return apply_filters( 'um_api_output_format', $format ); - } - - - /** - * Log each API request, if enabled - * - * @param array $data - */ - private function log_request( $data = array() ) { - if ( ! $this->log_requests ) - return; - } - - - /** - * Retrieve the output data - */ - public function get_output() { - return $this->data; - } - - - /** - * Output Query in either JSON/XML. The query data is outputted as JSON - * by default - */ - public function output( $status_code = 200 ) { - global $wp_query; - - $format = $this->get_output_format(); - - status_header( $status_code ); - - /** - * UM hook - * - * @type action - * @title um_api_output_before - * @description Action before API output - * @input_vars - * [{"var":"$data","type":"array","desc":"API data"}, - * {"var":"$rest_api","type":"object","desc":"REST API class"}, - * {"var":"$format","type":"string","desc":"Format"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_api_output_before', 'function_name', 10, 3 ); - * @example - * - */ - do_action( 'um_api_output_before', $this->data, $this, $format ); - - switch ( $format ) : - - case 'xml' : - - require_once um_path . 'includes/lib/array2xml.php'; - $xml = Array2XML::createXML( 'um', $this->data ); - echo $xml->saveXML(); - - break; - - case 'json' : - case '' : - - header( 'Content-Type: application/json' ); - if ( ! empty( $this->pretty_print ) ) - echo json_encode( $this->data, $this->pretty_print ); - else - echo json_encode( $this->data ); - - break; - - - default : - - // Allow other formats to be added via extensions - /** - * UM hook - * - * @type action - * @title um_api_output_{$format} - * @description Action before API output - * @input_vars - * [{"var":"$data","type":"array","desc":"API data"}, - * {"var":"$rest_api","type":"object","desc":"REST API class"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_api_output_{$format}', 'function_name', 10, 2 ); - * @example - * - */ - do_action( 'um_api_output_' . $format, $this->data, $this ); - - break; - - endswitch; - - /** - * UM hook - * - * @type action - * @title um_api_output_after - * @description Action after API output - * @input_vars - * [{"var":"$data","type":"array","desc":"API data"}, - * {"var":"$rest_api","type":"object","desc":"REST API class"}, - * {"var":"$format","type":"string","desc":"Format"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_api_output_after', 'function_name', 10, 3 ); - * @example - * - */ - do_action( 'um_api_output_after', $this->data, $this, $format ); - - die(); - } - - - /** - * Modify User Profile Page fields - * - * @param $content - * @param $user - * @return string - */ - function user_key_field( $content, $user ) { - if ( empty( $user ) ) - return $content; - - if( ! isset( $user->ID ) ) - return $content; - - if ( current_user_can( 'edit_users' ) && current_user_can( 'edit_user', $user->ID ) ) { - $user = get_userdata( $user->ID ); - - ob_start(); ?> - - - - - - - - -
- - - um_user_public_key ) ) { ?> -

-

- -

-  um_user_public_key; ?>
-  um_user_secret_key; ?>
-  get_token( $user->ID ); ?> -

-

-

- -
- - um_user_public_key ) ) { - update_user_meta( $user_id, 'um_user_public_key', $this->generate_public_key( $user->user_email ) ); - update_user_meta( $user_id, 'um_user_secret_key', $this->generate_private_key( $user->ID ) ); - } elseif( $regenerate == true ) { - $this->revoke_api_key( $user->ID ); - update_user_meta( $user_id, 'um_user_public_key', $this->generate_public_key( $user->user_email ) ); - update_user_meta( $user_id, 'um_user_secret_key', $this->generate_private_key( $user->ID ) ); - } else { - return false; - } - - return true; - } - - - /** - * Revoke a users API keys - * - * @param int $user_id - * - * @return bool - */ - public function revoke_api_key( $user_id = 0 ) { - - if( empty( $user_id ) ) { - return false; - } - - $user = get_userdata( $user_id ); - - if( ! $user ) { - return false; - } - - if ( ! empty( $user->um_user_public_key ) ) { - delete_transient( md5( 'um_api_user_' . $user->um_user_public_key ) ); - delete_user_meta( $user_id, 'um_user_public_key' ); - delete_user_meta( $user_id, 'um_user_secret_key' ); - } else { - return false; - } - - return true; - } - - - /** - * Generate and Save API key - * - * @param $user_id - */ - public function update_key( $user_id ) { - if ( current_user_can( 'edit_user', $user_id ) && isset( $_POST['um_set_api_key'] ) ) { - - $user = get_userdata( $user_id ); - - if ( empty( $user->um_user_public_key ) ) { - update_user_meta( $user_id, 'um_user_public_key', $this->generate_public_key( $user->user_email ) ); - update_user_meta( $user_id, 'um_user_secret_key', $this->generate_private_key( $user->ID ) ); - } else { - $this->revoke_api_key( $user_id ); - } - } - } - - - /** - * Generate the public key for a user - * - * @param string $user_email - * - * @return string - */ - private function generate_public_key( $user_email = '' ) { - $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : ''; - $public = hash( 'md5', $user_email . $auth_key . date( 'U' ) ); - return $public; - } - - - /** - * Generate the secret key for a user - * - * @param int $user_id - * - * @return string - */ - private function generate_private_key( $user_id = 0 ) { - $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : ''; - $secret = hash( 'md5', $user_id . $auth_key . date( 'U' ) ); - return $secret; - } - - - /** - * Retrieve the user's token - * - * @param int $user_id - * - * @return string - */ - private function get_token( $user_id = 0 ) { - $user = get_userdata( $user_id ); - return hash( 'md5', $user->um_user_secret_key . $user->um_user_public_key ); - } - - } -} \ No newline at end of file diff --git a/includes/core/rest/class-api-v1.php b/includes/core/rest/class-api-v1.php new file mode 100644 index 00000000..e7de1394 --- /dev/null +++ b/includes/core/rest/class-api-v1.php @@ -0,0 +1,541 @@ +vars = $vars; + + return $vars; + } + + + /** + * Validate the API request + */ + protected function validate_request() { + global $wp_query; + + $this->override = false; + + // Make sure we have both user and api key + if ( ! empty( $wp_query->query_vars['um-api'] ) ) { + + if ( empty( $wp_query->query_vars['token'] ) || empty( $wp_query->query_vars['key'] ) ) { + $this->missing_auth(); + } + + // Retrieve the user by public API key and ensure they exist + if ( ! ( $user = $this->get_user( $wp_query->query_vars['key'] ) ) ) { + $this->invalid_key(); + } else { + $token = urldecode( $wp_query->query_vars['token'] ); + $secret = get_user_meta( $user, 'um_user_secret_key', true ); + $public = urldecode( $wp_query->query_vars['key'] ); + + if ( hash_equals( md5( $secret . $public ), $token ) ) { + $this->is_valid_request = true; + } else { + $this->invalid_auth(); + } + } + + } + } + + + /** + * Retrieve the user ID based on the public key provided + * + * @param string $key + * + * @return bool|mixed|null|string + */ + public function get_user( $key = '' ) { + global $wpdb, $wp_query; + + if ( empty( $key ) ) { + $key = urldecode( $wp_query->query_vars['key'] ); + } + + if ( empty( $key ) ) { + return false; + } + + $user = get_transient( md5( 'um_api_user_' . $key ) ); + + if ( false === $user ) { + $user = $wpdb->get_var( $wpdb->prepare( + "SELECT user_id + FROM $wpdb->usermeta + WHERE meta_key = 'um_user_public_key' AND + meta_value = %s + LIMIT 1", + $key + ) ); + set_transient( md5( 'um_api_user_' . $key ) , $user, DAY_IN_SECONDS ); + } + + if ( $user != null ) { + $this->user_id = $user; + return $user; + } + + return false; + } + + + /** + * Process Get users API Request + * + * @param $args + * + * @return array + */ + public function get_users( $args ) { + /** + * @var int $number + * @var string $orderby + * @var string $order + * @var string $include + * @var string $exclude + */ + extract( $args ); + + $response = array(); + + if ( ! $number ) { + $number = 10; + } + + if ( ! $orderby ) { + $orderby = 'user_registered'; + } + + if ( ! $order ) { + $order = 'desc'; + } + + $loop_a = array( 'number' => $number, 'orderby' => $orderby, 'order' => $order ); + + if ( $include ) { + $include = explode(',', $include ); + $loop_a['include'] = $include; + } + + if ( $exclude ) { + $exclude = explode(',', $exclude ); + $loop_a['exclude'] = $exclude; + } + + $loop = get_users( $loop_a ); + + foreach ( $loop as $user ) { + + unset( $user->data->user_status ); + unset( $user->data->user_activation_key ); + unset( $user->data->user_pass ); + + um_fetch_user( $user->ID ); + + foreach ( $user as $key => $val ) { + if ( $key != 'data' ) { + continue; + } + + $key = 'profile'; + $val->roles = $user->roles; + $val->first_name = um_user('first_name'); + $val->last_name = um_user('last_name'); + $val->account_status = um_user('account_status'); + $val->profile_pic_original = um_get_user_avatar_url('', 'original'); + $val->profile_pic_normal = um_get_user_avatar_url('', 200); + $val->profile_pic_small = um_get_user_avatar_url('', 40); + $val->cover_photo = $this->getsrc( um_user('cover_photo', 1000) ); + + /** + * UM hook + * + * @type filter + * @title um_rest_userdata + * @description Change output data for Rest API userdata call + * @input_vars + * [{"var":"$value","type":"array","desc":"Output Data"}, + * {"var":"$user_id","type":"string","desc":"User ID"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $val = apply_filters( 'um_rest_userdata', $val, $user->ID ); + $response[ $user->ID ] = $val; + } + } + + return $response; + } + + + /** + * Update user API query + * + * @param $args + * + * @return array + */ + public function update_user( $args ) { + /** + * @var int $id + * @var string $data + * @var string $value + */ + extract( $args ); + + $response = array(); + $error = array(); + + if ( ! $id ) { + $error['error'] = __( 'You must provide a user ID', 'ultimate-member' ); + return $error; + } + + if ( ! $data ) { + $error['error'] = __( 'You need to provide data to update', 'ultimate-member' ); + return $error; + } + + um_fetch_user( $id ); + + switch ( $data ) { + case 'status': + UM()->user()->set_status( $value ); + $response['success'] = __( 'User status has been changed.', 'ultimate-member' ); + break; + case 'role': + $wp_user_object = new \WP_User( $id ); + $old_roles = $wp_user_object->roles; + $wp_user_object->set_role( $value ); + + /** + * UM hook + * + * @type action + * @title um_after_member_role_upgrade + * @description Action after user role was changed + * @input_vars + * [{"var":"$new_roles","type":"array","desc":"New User Roles"}, + * {"var":"$old_roles","type":"array","desc":"Old roles"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_after_member_role_upgrade', 'function_name', 10, 2 ); + * @example + * + */ + do_action( 'um_after_member_role_upgrade', array( $value ), $old_roles, $id ); + + $response['success'] = __( 'User role has been changed.', 'ultimate-member' ); + break; + default: + update_user_meta( $id, $data, esc_attr( $value ) ); + $response['success'] = __( 'User meta has been changed.', 'ultimate-member' ); + break; + } + + return $response; + } + + + /** + * Process delete user via API + * + * @param $args + * + * @return array + */ + public function delete_user( $args ) { + /** + * @var int $id + */ + extract( $args ); + + $response = array(); + $error = array(); + + if ( ! isset( $id ) ) { + $error['error'] = __( 'You must provide a user ID', 'ultimate-member' ); + return $error; + } + + $user = get_userdata( $id ); + if ( ! $user ) { + $error['error'] = __( 'Invalid user specified', 'ultimate-member' ); + return $error; + } + + um_fetch_user( $id ); + UM()->user()->delete(); + + $response['success'] = __( 'User has been successfully deleted.', 'ultimate-member' ); + + return $response; + } + + + /** + * Process Get user API Request + * + * @param $args + * + * @return array|mixed + */ + public function get_auser( $args ) { + /** + * @var int $um_id + * @var string $um_fields + */ + extract( $args ); + + $response = array(); + $error = array(); + + if ( ! isset( $id ) ) { + $error['error'] = __('You must provide a user ID','ultimate-member'); + return $error; + } + + $user = get_userdata( $id ); + if ( ! $user ) { + $error['error'] = __('Invalid user specified','ultimate-member'); + return $error; + } + + unset( $user->data->user_status ); + unset( $user->data->user_activation_key ); + unset( $user->data->user_pass ); + + um_fetch_user( $user->ID ); + + if ( isset( $fields ) && $fields ) { + $fields = explode(',', $fields ); + $response['ID'] = $user->ID; + $response['username'] = $user->user_login; + foreach ( $fields as $field ) { + + switch ( $field ) { + + default: + $response[ $field ] = ( um_profile( $field ) ) ? um_profile( $field ) : ''; + + /** + * UM hook + * + * @type filter + * @title um_rest_get_auser + * @description Change output data for Rest API user authentification call + * @input_vars + * [{"var":"$response","type":"array","desc":"Output Data"}, + * {"var":"$field","type":"string","desc":"Field Key"}, + * {"var":"$user_id","type":"int","desc":"User ID"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $response = apply_filters( 'um_rest_get_auser', $response, $field, $user->ID ); + break; + + case 'cover_photo': + $response['cover_photo'] = $this->getsrc( um_user('cover_photo', 1000) ); + break; + + case 'profile_pic': + $response['profile_pic_original'] = um_get_user_avatar_url('', 'original'); + $response['profile_pic_normal'] = um_get_user_avatar_url('', 200); + $response['profile_pic_small'] = um_get_user_avatar_url('', 40); + break; + + case 'status': + $response['status'] = um_user('account_status'); + break; + + case 'role': + //get priority role here + $response['role'] = um_user( 'role' ); + break; + + case 'email': + case 'user_email': + $response['email'] = um_user('user_email'); + break; + + } + + } + } else { + + foreach ( $user as $key => $val ) { + if ( $key != 'data' ) { + continue; + } + + $key = 'profile'; + $val->roles = $user->roles; + $val->first_name = um_user( 'first_name' ); + $val->last_name = um_user('last_name' ); + $val->account_status = um_user( 'account_status' ); + $val->profile_pic_original = um_get_user_avatar_url( '', 'original' ); + $val->profile_pic_normal = um_get_user_avatar_url( '', 200 ); + $val->profile_pic_small = um_get_user_avatar_url( '', 40 ); + $val->cover_photo = $this->getsrc( um_user( 'cover_photo', 1000 ) ); + + /** + * UM hook + * + * @type filter + * @title um_rest_userdata + * @description Change output data for Rest API userdata call + * @input_vars + * [{"var":"$value","type":"array","desc":"Output Data"}, + * {"var":"$user_id","type":"string","desc":"User ID"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $val = apply_filters( 'um_rest_userdata', $val, $user->ID ); + $response = $val; + } + + } + + return $response; + } + + + /** + * Get source + * + * @param $image + * + * @return string + */ + public function getsrc( $image ) { + if (preg_match('/query_vars['format'] ) ? $wp_query->query_vars['format'] : 'json'; + + /** + * UM hook + * + * @type filter + * @title um_api_output_format + * @description UM Rest API output format + * @input_vars + * [{"var":"$format","type":"string","desc":"Format"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + return apply_filters( 'um_api_output_format', $format ); + } + } +} \ No newline at end of file diff --git a/includes/core/rest/class-api-v2.php b/includes/core/rest/class-api-v2.php new file mode 100644 index 00000000..dcf875d5 --- /dev/null +++ b/includes/core/rest/class-api-v2.php @@ -0,0 +1,540 @@ +vars = $vars; + + return $vars; + } + + + /** + * Validate the API request + */ + protected function validate_request() { + global $wp_query; + + $this->override = false; + + // Make sure we have both user and api key + if ( ! empty( $wp_query->query_vars['um-api'] ) ) { + + if ( empty( $wp_query->query_vars['um_token'] ) || empty( $wp_query->query_vars['um_key'] ) ) { + $this->missing_auth(); + } + + // Retrieve the user by public API key and ensure they exist + if ( ! ( $user = $this->get_user( $wp_query->query_vars['um_key'] ) ) ) { + $this->invalid_key(); + } else { + $token = urldecode( $wp_query->query_vars['um_token'] ); + $secret = get_user_meta( $user, 'um_user_secret_key', true ); + $public = urldecode( $wp_query->query_vars['um_key'] ); + + if ( hash_equals( md5( $secret . $public ), $token ) ) { + $this->is_valid_request = true; + } else { + $this->invalid_auth(); + } + } + } + } + + + /** + * Retrieve the user ID based on the public key provided + * + * @param string $key + * + * @return bool|mixed|null|string + */ + public function get_user( $key = '' ) { + global $wpdb, $wp_query; + + if ( empty( $key ) ) { + $key = urldecode( $wp_query->query_vars['um_key'] ); + } + + if ( empty( $key ) ) { + return false; + } + + $user = get_transient( md5( 'um_api_user_' . $key ) ); + + if ( false === $user ) { + $user = $wpdb->get_var( $wpdb->prepare( + "SELECT user_id + FROM $wpdb->usermeta + WHERE meta_key = 'um_user_public_key' AND + meta_value = %s + LIMIT 1", + $key + ) ); + set_transient( md5( 'um_api_user_' . $key ) , $user, DAY_IN_SECONDS ); + } + + if ( $user != NULL ) { + $this->user_id = $user; + return $user; + } + + return false; + } + + + /** + * Process Get users API Request + * + * @param $args + * + * @return array + */ + public function get_users( $args ) { + /** + * @var int $um_number + * @var string $um_orderby + * @var string $um_order + * @var string $um_include + * @var string $um_exclude + */ + extract( $args ); + + $response = array(); + + if ( ! $um_number ) { + $um_number = 10; + } + + if ( ! $um_orderby ) { + $um_orderby = 'user_registered'; + } + + if ( ! $um_order ) { + $um_order = 'desc'; + } + + $loop_a = array( 'number' => $um_number, 'orderby' => $um_orderby, 'order' => $um_order ); + + if ( $um_include ) { + $um_include = explode(',', $um_include ); + $loop_a['include'] = $um_include; + } + + if ( $um_exclude ) { + $um_exclude = explode(',', $um_exclude ); + $loop_a['exclude'] = $um_exclude; + } + + $loop = get_users( $loop_a ); + + foreach ( $loop as $user ) { + + unset( $user->data->user_status ); + unset( $user->data->user_activation_key ); + unset( $user->data->user_pass ); + + um_fetch_user( $user->ID ); + + foreach ( $user as $key => $val ) { + if ( $key != 'data' ) { + continue; + } + + $key = 'profile'; + $val->roles = $user->roles; + $val->first_name = um_user( 'first_name' ); + $val->last_name = um_user( 'last_name' ); + $val->account_status = um_user( 'account_status' ); + $val->profile_pic_original = um_get_user_avatar_url( '', 'original' ); + $val->profile_pic_normal = um_get_user_avatar_url( '', 200 ); + $val->profile_pic_small = um_get_user_avatar_url( '', 40 ); + $val->cover_photo = $this->getsrc( um_user( 'cover_photo', 1000 ) ); + + /** + * UM hook + * + * @type filter + * @title um_rest_userdata + * @description Change output data for Rest API userdata call + * @input_vars + * [{"var":"$value","type":"array","desc":"Output Data"}, + * {"var":"$user_id","type":"string","desc":"User ID"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $val = apply_filters( 'um_rest_userdata', $val, $user->ID ); + + $response[ $user->ID ] = $val; + } + } + + return $response; + } + + + /** + * Update user API query + * + * @param $args + * + * @return array + */ + public function update_user( $args ) { + /** + * @var int $um_id + * @var string $um_data + * @var string $um_value + */ + extract( $args ); + + $response = array(); + $error = array(); + + if ( ! $um_id ) { + $error['error'] = __( 'You must provide a user ID', 'ultimate-member' ); + return $error; + } + + if ( ! $um_data ) { + $error['error'] = __( 'You need to provide data to update', 'ultimate-member' ); + return $error; + } + + um_fetch_user( $um_id ); + + switch ( $um_data ) { + case 'status': + UM()->user()->set_status( $um_value ); + $response['success'] = __( 'User status has been changed.', 'ultimate-member' ); + break; + case 'role': + $wp_user_object = new \WP_User( $um_id ); + $old_roles = $wp_user_object->roles; + $wp_user_object->set_role( $um_value ); + + /** + * UM hook + * + * @type action + * @title um_after_member_role_upgrade + * @description Action after user role was changed + * @input_vars + * [{"var":"$new_roles","type":"array","desc":"New User Roles"}, + * {"var":"$old_roles","type":"array","desc":"Old roles"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_after_member_role_upgrade', 'function_name', 10, 2 ); + * @example + * + */ + do_action( 'um_after_member_role_upgrade', array( $um_value ), $old_roles, $um_id ); + + $response['success'] = __( 'User role has been changed.', 'ultimate-member' ); + break; + default: + update_user_meta( $um_id, $um_data, esc_attr( $um_value ) ); + $response['success'] = __( 'User meta has been changed.', 'ultimate-member' ); + break; + } + + return $response; + } + + + /** + * Process delete user via API + * + * @param $args + * + * @return array + */ + public function delete_user( $args ) { + /** + * @var int $um_id + */ + extract( $args ); + + $response = array(); + $error = array(); + + if ( ! isset( $um_id ) ) { + $error['error'] = __( 'You must provide a user ID', 'ultimate-member' ); + return $error; + } + + $user = get_userdata( $um_id ); + if ( ! $user ) { + $error['error'] = __( 'Invalid user specified', 'ultimate-member' ); + return $error; + } + + um_fetch_user( $um_id ); + UM()->user()->delete(); + + $response['success'] = __( 'User has been successfully deleted.', 'ultimate-member' ); + + return $response; + } + + + /** + * Process Get user API Request + * + * @param $args + * + * @return array + */ + public function get_auser( $args ) { + /** + * @var int $um_id + * @var string $um_fields + */ + extract( $args ); + + $response = array(); + $error = array(); + + if ( ! isset( $um_id ) ) { + $error['error'] = __( 'You must provide a user ID', 'ultimate-member' ); + return $error; + } + + $user = get_userdata( $um_id ); + if ( ! $user ) { + $error['error'] = __('Invalid user specified','ultimate-member'); + return $error; + } + + unset( $user->data->user_status ); + unset( $user->data->user_activation_key ); + unset( $user->data->user_pass ); + + um_fetch_user( $user->ID ); + + if ( isset( $um_fields ) && $um_fields ) { + $um_fields = explode(',', $um_fields ); + $response['ID'] = $user->ID; + $response['username'] = $user->user_login; + foreach ( $um_fields as $field ) { + + switch ( $field ) { + + default: + $response[ $field ] = ( um_profile( $field ) ) ? um_profile( $field ) : ''; + + /** + * UM hook + * + * @type filter + * @title um_rest_get_auser + * @description Change output data for Rest API user authentification call + * @input_vars + * [{"var":"$response","type":"array","desc":"Output Data"}, + * {"var":"$field","type":"string","desc":"Field Key"}, + * {"var":"$user_id","type":"int","desc":"User ID"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $response = apply_filters( 'um_rest_get_auser', $response, $field, $user->ID ); + break; + + case 'cover_photo': + $response['cover_photo'] = $this->getsrc( um_user( 'cover_photo', 1000 ) ); + break; + + case 'profile_pic': + $response['profile_pic_original'] = um_get_user_avatar_url( '', 'original' ); + $response['profile_pic_normal'] = um_get_user_avatar_url( '', 200 ); + $response['profile_pic_small'] = um_get_user_avatar_url( '', 40 ); + break; + + case 'status': + $response['status'] = um_user( 'account_status' ); + break; + + case 'role': + //get priority role here + $response['role'] = um_user( 'role' ); + break; + + case 'email': + case 'user_email': + $response['email'] = um_user( 'user_email' ); + break; + } + } + } else { + + foreach ( $user as $key => $val ) { + if ( $key != 'data' ) { + continue; + } + if ( $key == 'data' ) { + $key = 'profile'; + $val->roles = $user->roles; + $val->first_name = um_user( 'first_name' ); + $val->last_name = um_user( 'last_name' ); + $val->account_status = um_user( 'account_status' ); + $val->profile_pic_original = um_get_user_avatar_url( '', 'original' ); + $val->profile_pic_normal = um_get_user_avatar_url( '', 200 ); + $val->profile_pic_small = um_get_user_avatar_url( '', 40 ); + $val->cover_photo = $this->getsrc( um_user( 'cover_photo', 1000 ) ); + + /** + * UM hook + * + * @type filter + * @title um_rest_userdata + * @description Change output data for Rest API userdata call + * @input_vars + * [{"var":"$value","type":"array","desc":"Output Data"}, + * {"var":"$user_id","type":"string","desc":"User ID"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $val = apply_filters( 'um_rest_userdata', $val, $user->ID ); + } + $response = $val; + } + + } + + return $response; + } + + + /** + * Get source + * + * @param $image + * + * @return string + */ + public function getsrc( $image ) { + if (preg_match('/query_vars['um_format'] ) ? $wp_query->query_vars['um_format'] : 'json'; + + /** + * UM hook + * + * @type filter + * @title um_api_output_format + * @description UM Rest API output format + * @input_vars + * [{"var":"$format","type":"string","desc":"Format"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + return apply_filters( 'um_api_output_format', $format ); + } + } +} \ No newline at end of file diff --git a/includes/core/rest/class-api.php b/includes/core/rest/class-api.php new file mode 100644 index 00000000..ef8c3fb3 --- /dev/null +++ b/includes/core/rest/class-api.php @@ -0,0 +1,615 @@ +pretty_print = defined( 'JSON_PRETTY_PRINT' ) ? JSON_PRETTY_PRINT : null; + + /** + * UM hook + * + * @type filter + * @title um_api_log_requests + * @description Allow API request logging to be turned off + * @input_vars + * [{"var":"$allow_log","type":"bool","desc":"Enable api logs"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $this->log_requests = apply_filters( 'um_api_log_requests', $this->log_requests ); + } + + + /** + * Registers a new rewrite endpoint for accessing the API + * + * @param $rewrite_rules + */ + public function add_endpoint( $rewrite_rules ) { + add_rewrite_endpoint( 'um-api', EP_ALL ); + } + + + /** + * Listens for the API and then processes the API requests + */ + public function process_query() { + global $wp_query; + + // Check for um-api var. Get out if not present + if ( ! isset( $wp_query->query_vars['um-api'] ) ) { + return; + } + + // Check for a valid user and set errors if necessary + $this->validate_request(); + + // Only proceed if no errors have been noted + if ( ! $this->is_valid_request ) { + return; + } + + if ( ! defined( 'UM_DOING_API' ) ) { + define( 'UM_DOING_API', true ); + } + + // Determine the kind of query + $args = array(); + $query_mode = $this->get_query_mode(); + foreach ( $this->vars as $k ) { + $args[ $k ] = isset( $wp_query->query_vars[ $k ] ) ? $wp_query->query_vars[ $k ] : null; + } + + $data = array(); + + switch ( $query_mode ) { + case 'get.stats': + $data = $this->get_stats( $args ); + break; + + case 'get.users': + $data = $this->get_users( $args ); + break; + + case 'get.user': + $data = $this->get_auser( $args ); + break; + + case 'update.user': + $data = $this->update_user( $args ); + break; + + case 'delete.user': + $data = $this->delete_user( $args ); + break; + + default: + /** + * UM hook + * + * @type filter + * @title um_rest_query_mode + * @description Change query attributes + * @input_vars + * [{"var":"$data","type":"array","desc":"Query Data"}, + * {"var":"$query_mode","type":"string","desc":"Query Mode"}, + * {"var":"$args","type":"array","desc":"Query Arguments"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $data = apply_filters( 'um_rest_query_mode', $data, $query_mode, $args ); + break; + } + + /** + * UM hook + * + * @type filter + * @title um_api_output_data + * @description Change output data for Rest API call + * @input_vars + * [{"var":"$data","type":"array","desc":"Output Data"}, + * {"var":"$query_mode","type":"string","desc":"Query Mode"}, + * {"var":"$api_class","type":"REST_API","desc":"REST_API instance"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $this->data = apply_filters( 'um_api_output_data', $data, $query_mode, $this ); + + // Log this API request, if enabled. We log it here because we have access to errors. + $this->log_request( $this->data ); + + // Send out data to the output function + $this->output(); + } + + + /** + * Validate the API request + */ + protected function validate_request() { + + } + + + /** + * Retrieve the user ID based on the public key provided + * + * @param string $key + * + * @return bool + */ + public function get_user( $key = '' ) { + return false; + } + + + /** + * Displays a missing authentication error if all the parameters aren't + * provided + */ + protected function missing_auth() { + $error = array(); + $error['error'] = __( 'You must specify both a token and API key!', 'ultimate-member' ); + + $this->data = $error; + $this->output( 401 ); + } + + + /** + * Displays an authentication failed error if the user failed to provide valid credentials + */ + protected function invalid_auth() { + $error = array(); + $error['error'] = __( 'Your request could not be authenticated', 'ultimate-member' ); + + $this->data = $error; + $this->output( 401 ); + } + + + /** + * Displays an invalid API key error if the API key provided couldn't be validated + */ + protected function invalid_key() { + $error = array(); + $error['error'] = __( 'Invalid API key', 'ultimate-member' ); + + $this->data = $error; + $this->output( 401 ); + } + + + /** + * Get some stats + * + * @param $args + * + * @return array + */ + public function get_stats( $args ) { + global $wpdb; + + $response = array(); + + $count = absint( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}users" ) ); + $response['stats']['total_users'] = $count; + + $pending = UM()->user()->get_pending_users_count(); + $response['stats']['pending_users'] = absint( $pending ); + + /** + * UM hook + * + * @type filter + * @title um_rest_api_get_stats + * @description Change output data for Rest API get stats call + * @input_vars + * [{"var":"$response","type":"array","desc":"Output Data"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $response = apply_filters( 'um_rest_api_get_stats', $response ); + return $response; + } + + + /** + * Process Get users API Request + * + * @param $args + * + * @return array + */ + public function get_users( $args ) { + return array(); + } + + + /** + * Update user API query + * + * @param $args + * + * @return array + */ + public function update_user( $args ) { + return array(); + } + + + /** + * Process delete user via API + * + * @param $args + * + * @return array + */ + public function delete_user( $args ) { + return array(); + } + + + /** + * Process Get user API Request + * + * @param $args + * + * @return array + */ + public function get_auser( $args ) { + return array(); + } + + + /** + * Get source + * + * @param $image + * + * @return string + */ + protected function getsrc( $image ) { + if ( preg_match( '/ + * @example + * + */ + $accepted = apply_filters( 'um_api_valid_query_modes', array( + 'get.users', + 'get.user', + 'update.user', + 'delete.user', + 'get.following', + 'get.followers', + 'get.stats', + ) ); + + $query = isset( $wp_query->query_vars['um-api'] ) ? $wp_query->query_vars['um-api'] : null; + $error = array(); + // Make sure our query is valid + if ( ! in_array( $query, $accepted ) ) { + $error['error'] = __( 'Invalid query!', 'ultimate-member' ); + + $this->data = $error; + $this->output(); + } + + return $query; + } + + + /** + * Get page number + */ + public function get_paged() { + global $wp_query; + + return isset( $wp_query->query_vars['page'] ) ? $wp_query->query_vars['page'] : 1; + } + + + /** + * Retrieve the output format + */ + public function get_output_format() { + /** + * UM hook + * + * @type filter + * @title um_api_output_format + * @description UM Rest API output format + * @input_vars + * [{"var":"$format","type":"string","desc":"Format"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + return apply_filters( 'um_api_output_format', 'json' ); + } + + + /** + * Log each API request, if enabled + * + * @param array $data + */ + protected function log_request( $data = array() ) { + if ( ! $this->log_requests ) { + return; + } + } + + + /** + * Retrieve the output data + */ + public function get_output() { + return $this->data; + } + + + /** + * Output Query in either JSON/XML. The query data is outputted as JSON + * by default + * + * @param int $status_code + */ + public function output( $status_code = 200 ) { + $format = $this->get_output_format(); + + status_header( $status_code ); + + /** + * UM hook + * + * @type action + * @title um_api_output_before + * @description Action before API output + * @input_vars + * [{"var":"$data","type":"array","desc":"API data"}, + * {"var":"$rest_api","type":"object","desc":"REST API class"}, + * {"var":"$format","type":"string","desc":"Format"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_api_output_before', 'function_name', 10, 3 ); + * @example + * + */ + do_action( 'um_api_output_before', $this->data, $this, $format ); + + switch ( $format ) { + + case 'xml' : + + require_once um_path . 'includes/lib/array2xml.php'; + $xml = \Array2XML::createXML( 'um', $this->data ); + echo $xml->saveXML(); + + break; + + case 'json' : + case '' : + + header( 'Content-Type: application/json' ); + if ( ! empty( $this->pretty_print ) ) { + echo json_encode( $this->data, $this->pretty_print ); + } else { + echo json_encode( $this->data ); + } + + break; + + + default : + + // Allow other formats to be added via extensions + /** + * UM hook + * + * @type action + * @title um_api_output_{$format} + * @description Action before API output + * @input_vars + * [{"var":"$data","type":"array","desc":"API data"}, + * {"var":"$rest_api","type":"object","desc":"REST API class"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_api_output_{$format}', 'function_name', 10, 2 ); + * @example + * + */ + do_action( 'um_api_output_' . $format, $this->data, $this ); + + break; + } + + /** + * UM hook + * + * @type action + * @title um_api_output_after + * @description Action after API output + * @input_vars + * [{"var":"$data","type":"array","desc":"API data"}, + * {"var":"$rest_api","type":"object","desc":"REST API class"}, + * {"var":"$format","type":"string","desc":"Format"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_api_output_after', 'function_name', 10, 3 ); + * @example + * + */ + do_action( 'um_api_output_after', $this->data, $this, $format ); + + die(); + } + + } +} \ No newline at end of file