Ticket #40702: 40702.7.diff
File 40702.7.diff, 23.4 KB (added by , 7 years ago) |
---|
-
src/wp-admin/admin-ajax.php
64 64 'parse-media-shortcode', 'destroy-sessions', 'install-plugin', 'update-plugin', 'press-this-save-post', 65 65 'press-this-add-category', 'crop-image', 'generate-password', 'save-wporg-username', 'delete-plugin', 66 66 'search-plugins', 'search-install-plugins', 'activate-plugin', 'update-theme', 'delete-theme', 67 'install-theme', 'get-post-thumbnail-html', 'get-community-events',67 'install-theme', 'get-post-thumbnail-html', 68 68 ); 69 69 70 70 // Deprecated -
src/wp-admin/includes/ajax-actions.php
297 297 } 298 298 299 299 /** 300 * Handles AJAX requests for community events301 *302 * @since 4.8.0303 */304 function wp_ajax_get_community_events() {305 require_once( ABSPATH . 'wp-admin/includes/class-wp-community-events.php' );306 307 check_ajax_referer( 'community_events' );308 309 $search = isset( $_POST['location'] ) ? wp_unslash( $_POST['location'] ) : '';310 $timezone = isset( $_POST['timezone'] ) ? wp_unslash( $_POST['timezone'] ) : '';311 $user_id = get_current_user_id();312 $saved_location = get_user_option( 'community-events-location', $user_id );313 $events_client = new WP_Community_Events( $user_id, $saved_location );314 $events = $events_client->get_events( $search, $timezone );315 316 if ( is_wp_error( $events ) ) {317 wp_send_json_error( array(318 'error' => $events->get_error_message(),319 ) );320 } else {321 if ( isset( $events['location'] ) ) {322 // Send only the data that the client will use.323 $events['location'] = $events['location']['description'];324 325 // Store the location network-wide, so the user doesn't have to set it on each site.326 update_user_option( $user_id, 'community-events-location', $events['location'], true );327 }328 329 wp_send_json_success( $events );330 }331 }332 333 /**334 300 * Ajax handler for dashboard widgets. 335 301 * 336 302 * @since 3.4.0 -
src/wp-admin/includes/dashboard.php
144 144 $events_client = new WP_Community_Events( $user_id, $user_location ); 145 145 146 146 $script_data = array( 147 'nonce' => wp_create_nonce( 'community_events' ), 147 'rest_url' => rest_url( '/' ), 148 'rest_nonce' => wp_create_nonce( 'wp_rest' ), 148 149 'cache' => $events_client->get_cached_events(), 149 150 150 151 'l10n' => array( … … 1225 1226 <?php printf( 1226 1227 /* translators: %s is a placeholder for the name of a city. */ 1227 1228 __( 'Attend an upcoming event near %s.' ), 1228 '<strong>{{ data.location }}</strong>'1229 '<strong>{{ data.location.description }}</strong>' 1229 1230 ); ?> 1230 1231 </script> 1231 1232 … … 1247 1248 </div> 1248 1249 </div> 1249 1250 1250 <div class="event-date-time"> 1251 <span class="event-date">{{ event.formatted_date }}</span> 1252 <# if ( 'meetup' === event.type ) { #> 1253 <span class="event-time">{{ event.formatted_time }}</span> 1254 <# } #> 1255 </div> 1251 <# if ( event.date && event.date.formatted ) { #> 1252 <div class="event-date-time"> 1253 <span class="event-date">{{ event.date.formatted.date }}</span> 1254 <# if ( 'meetup' === event.type ) { #> 1255 <span class="event-time">{{ event.date.formatted.time }}</span> 1256 <# } #> 1257 </div> 1258 <# } #> 1256 1259 </li> 1257 1260 <# } ) #> 1258 1261 </script> … … 1262 1265 <?php printf( 1263 1266 /* translators: 1: the city the user searched for, 2: meetup organization documentation URL */ 1264 1267 __( 'There aren’t any events scheduled near %1$s at the moment. Would you like to <a href="%2$s">organize one</a>?' ), 1265 '{{data.location }}',1268 '{{data.location.description}}', 1266 1269 __( 'https://make.wordpress.org/community/handbook/meetup-organizer/welcome/' ) 1267 1270 ); ?> 1268 1271 </li> -
src/wp-admin/js/dashboard.js
191 191 192 192 jQuery( function( $ ) { 193 193 'use strict'; 194 194 195 195 var communityEventsData = window.communityEventsData || {}; 196 196 197 197 var app = window.wp.communityEvents = { … … 291 291 $spinner = $( '.community-events-form' ).children( '.spinner' ); 292 292 293 293 requestParams = requestParams || {}; 294 requestParams._wpnonce = communityEventsData.nonce;295 294 requestParams.timezone = window.Intl ? window.Intl.DateTimeFormat().resolvedOptions().timeZone : ''; 296 295 297 296 initiatedBy = requestParams.location ? 'user' : 'app'; 298 297 299 298 $spinner.addClass( 'is-active' ); 300 299 301 wp.ajax.post( 'get-community-events', requestParams ) 302 .always( function() { 303 $spinner.removeClass( 'is-active' ); 304 }) 305 306 .done( function( response ) { 307 if ( 'no_location_available' === response.error ) { 308 if ( requestParams.location ) { 309 response.unknownCity = requestParams.location; 310 } else { 311 /* 312 * No location was passed, which means that this was an automatic query 313 * based on IP, locale, and timezone. Since the user didn't initiate it, 314 * it should fail silently. Otherwise, the error could confuse and/or 315 * annoy them. 316 */ 317 318 delete response.error; 319 } 320 } 321 app.renderEventsTemplate( response, initiatedBy ); 322 }) 300 requestParams._embed = 1; 323 301 324 .fail( function() { 302 $.ajax( communityEventsData.rest_url + 'wp/dashboard/v1/community-events/location/me', { 303 method: 'GET', 304 data: requestParams, 305 dataType: 'json', 306 headers: { 307 'X-WP-Nonce': communityEventsData.rest_nonce 308 }, 309 success: function( response ) { 310 var events = response._embedded ? response._embedded.events[0] : []; 311 var location = response; 312 313 delete location._embedded; 314 delete location._links; 315 316 app.renderEventsTemplate({ 317 location: location, 318 events: events 319 }, initiatedBy ); 320 }, 321 error: function() { 325 322 app.renderEventsTemplate( { 326 323 'location' : false, 327 324 'error' : true 328 325 }, initiatedBy ); 329 }); 326 }, 327 complete: function() { 328 $spinner.removeClass( 'is-active' ); 329 } 330 }); 330 331 }, 331 332 332 333 /** -
src/wp-includes/rest-api/endpoints/dashboard/class-wp-rest-community-events-events-controller.php
1 <?php 2 /** 3 * REST API: WP_REST_Community_Events_Events_Controller class 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 4.8.0 8 */ 9 10 /** 11 * Core class to access community events via the REST API. 12 * 13 * @since 4.8.0 14 * 15 * @see WP_REST_Controller 16 */ 17 class WP_REST_Community_Events_Events_Controller extends WP_REST_Controller { 18 19 /** 20 * Constructor. 21 * 22 * @since 4.8.0 23 * @access public 24 */ 25 public function __construct() { 26 $this->namespace = 'wp/dashboard/v1'; 27 $this->rest_base = 'community-events/events'; 28 } 29 30 /** 31 * Registers the routes for the objects of the controller. 32 * 33 * @since 4.8.0 34 * @access public 35 * 36 * @see register_rest_route() 37 */ 38 public function register_routes() { 39 40 register_rest_route( $this->namespace, '/' . $this->rest_base . '/me', array( 41 array( 42 'methods' => WP_REST_Server::READABLE, 43 'callback' => array( $this, 'get_current_items' ), 44 'permission_callback' => array( $this, 'get_current_items_permissions_check' ), 45 'args' => $this->get_collection_params(), 46 ), 47 'schema' => array( $this, 'get_public_item_schema' ), 48 ) ); 49 } 50 51 /** 52 * Checks whether a given request has permission to read community events. 53 * 54 * @since 4.8.0 55 * @access public 56 * 57 * @param WP_REST_Request $request Full details about the request. 58 * @return WP_Error|true True if the request has read access, WP_Error object otherwise. 59 */ 60 public function get_current_items_permissions_check( $request ) { 61 if ( ! is_user_logged_in() ) { 62 return new WP_Error( 'rest_not_logged_in', __( 'You are not currently logged in.' ), array( 'status' => 401 ) ); 63 } 64 65 return true; 66 } 67 68 /** 69 * Retrieves community events. 70 * 71 * @since 4.8.0 72 * @access public 73 * 74 * @param WP_REST_Request $request Full details about the request. 75 * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. 76 */ 77 public function get_current_items( $request ) { 78 require_once( ABSPATH . 'wp-admin/includes/class-wp-community-events.php' ); 79 80 $user_id = get_current_user_id(); 81 82 $location = $request->get_param( 'location' ); 83 $timezone = $request->get_param( 'timezone' ); 84 85 $saved_location = get_user_option( 'community-events-location', $user_id ); 86 $events_client = new WP_Community_Events( $user_id, $saved_location ); 87 $events = $events_client->get_events( $location, $timezone ); 88 89 $data = array(); 90 91 // Store the location network-wide, so the user doesn't have to set it on each site. 92 if ( ! is_wp_error( $events ) ) { 93 if ( isset( $events['location'] ) ) { 94 update_user_option( $user_id, 'community-events-location', $events['location'], true ); 95 } 96 97 if ( isset( $events['events'] ) ) { 98 foreach ( $events['events'] as $event ) { 99 $data[] = $this->prepare_item_for_response( $event, $request ); 100 } 101 } 102 } 103 104 return rest_ensure_response( $data ); 105 } 106 107 /** 108 * Prepares a single event output for response. 109 * 110 * @since 4.8.0 111 * @access public 112 * 113 * @param array $event Event data array from the API. 114 * @param WP_REST_Request $request Request object. 115 * @return WP_REST_Response Response object. 116 */ 117 public function prepare_item_for_response( $event, $request ) { 118 $data = array(); 119 120 $keys_to_copy = array( 'type', 'title', 'url', 'meetup', 'meetup_url' ); 121 foreach ( $keys_to_copy as $key ) { 122 if ( isset( $event[ $key ] ) ) { 123 $data[ $key ] = $event[ $key ]; 124 } else { 125 $data[ $key ] = null; 126 } 127 } 128 129 $data['date'] = array( 130 'raw' => isset( $event['date'] ) ? $event['date'] : null, 131 'formatted' => array( 132 'date' => isset( $event['formatted_date'] ) ? $event['formatted_date'] : null, 133 'time' => isset( $event['formatted_time'] ) ? $event['formatted_time'] : null, 134 ), 135 ); 136 137 $data['location'] = isset( $event['location'] ) ? $event['location'] : null; 138 139 return $data; 140 } 141 142 /** 143 * Retrieves a community event's schema, conforming to JSON Schema. 144 * 145 * @since 4.8.0 146 * @access public 147 * 148 * @return array Item schema data. 149 */ 150 public function get_item_schema() { 151 return array( 152 '$schema' => 'http://json-schema.org/schema#', 153 'title' => 'community_event', 154 'type' => 'object', 155 'properties' => array( 156 'type' => array( 157 'description' => __( 'Type for the event.' ), 158 'type' => 'string', 159 'enum' => array( 'meetup', 'wordcamp' ), 160 'context' => array( 'view', 'edit', 'embed' ), 161 'readonly' => true, 162 ), 163 'title' => array( 164 'description' => __( 'Title for the event.' ), 165 'type' => 'string', 166 'context' => array( 'view', 'edit', 'embed' ), 167 'readonly' => true, 168 ), 169 'url' => array( 170 'description' => __( 'Website URL for the event.' ), 171 'type' => 'string', 172 'context' => array( 'view', 'edit', 'embed' ), 173 'readonly' => true, 174 ), 175 'meetup' => array( 176 'description' => __( 'Name of the meetup, if the event is a meetup.' ), 177 'type' => 'string', 178 'context' => array( 'view', 'edit', 'embed' ), 179 'readonly' => true, 180 ), 181 'meetup_url' => array( 182 'description' => __( 'URL for the meetup on meetup.com, if the event is a meetup.' ), 183 'type' => 'string', 184 'context' => array( 'view', 'edit', 'embed' ), 185 'readonly' => true, 186 ), 187 'date' => array( 188 'description' => __( 'Date and time information for the event.' ), 189 'type' => 'object', 190 'context' => array( 'view', 'edit', 'embed' ), 191 'readonly' => true, 192 'properties' => array( 193 'raw' => array( 194 'description' => __( 'Unformatted date and time string.' ), 195 'type' => 'string', 196 'format' => 'date-time', 197 'context' => array( 'view', 'edit', 'embed' ), 198 'readonly' => true, 199 ), 200 'formatted' => array( 201 'description' => __( 'Formatted date and time information for the event.' ), 202 'type' => 'object', 203 'context' => array( 'view', 'edit', 'embed' ), 204 'readonly' => true, 205 'properties' => array( 206 'date' => array( 207 'description' => __( 'Formatted event date.' ), 208 'type' => 'string', 209 'context' => array( 'view', 'edit', 'embed' ), 210 'readonly' => true, 211 ), 212 'time' => array( 213 'description' => __( 'Formatted event time.' ), 214 'type' => 'string', 215 'context' => array( 'view', 'edit', 'embed' ), 216 'readonly' => true, 217 ), 218 ), 219 ), 220 ), 221 ), 222 'location' => array( 223 'description' => __( 'Location information for the event.' ), 224 'type' => 'object', 225 'context' => array( 'view', 'edit', 'embed' ), 226 'readonly' => true, 227 'properties' => array( 228 'location' => array( 229 'description' => __( 'Location name for the event.' ), 230 'type' => 'string', 231 'context' => array( 'view', 'edit', 'embed' ), 232 'readonly' => true, 233 ), 234 'country' => array( 235 'description' => __( 'Two-letter country code for the event.' ), 236 'type' => 'string', 237 'context' => array( 'view', 'edit', 'embed' ), 238 'readonly' => true, 239 ), 240 'latitude' => array( 241 'description' => __( 'Latitude for the event.' ), 242 'type' => 'number', 243 'context' => array( 'view', 'edit', 'embed' ), 244 'readonly' => true, 245 ), 246 'longitude' => array( 247 'description' => __( 'Longitude for the event.' ), 248 'type' => 'number', 249 'context' => array( 'view', 'edit', 'embed' ), 250 'readonly' => true, 251 ), 252 ), 253 ), 254 ), 255 ); 256 } 257 258 /** 259 * Retrieves the query params for collections. 260 * 261 * @since 4.8.0 262 * @access public 263 * 264 * @return array Collection parameters. 265 */ 266 public function get_collection_params() { 267 return array( 268 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 269 'location' => array( 270 'description' => __( 'Optional city name to help determine the location for the events.' ), 271 'type' => 'string', 272 'default' => '', 273 ), 274 'timezone' => array( 275 'description' => __( 'Optional timezone to help determine the location for the events.' ), 276 'type' => 'string', 277 'default' => '', 278 ), 279 ); 280 } 281 } -
src/wp-includes/rest-api/endpoints/dashboard/class-wp-rest-community-events-location-controller.php
1 <?php 2 /** 3 * REST API: WP_REST_Community_Events_Location_Controller class 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 4.8.0 8 */ 9 10 /** 11 * Core class to access community events user locations via the REST API. 12 * 13 * @since 4.8.0 14 * 15 * @see WP_REST_Controller 16 */ 17 class WP_REST_Community_Events_Location_Controller extends WP_REST_Controller { 18 19 /** 20 * Constructor. 21 * 22 * @since 4.8.0 23 * @access public 24 */ 25 public function __construct() { 26 $this->namespace = 'wp/dashboard/v1'; 27 $this->rest_base = 'community-events/location'; 28 } 29 30 /** 31 * Registers the routes for the objects of the controller. 32 * 33 * @since 4.8.0 34 * @access public 35 * 36 * @see register_rest_route() 37 */ 38 public function register_routes() { 39 40 register_rest_route( $this->namespace, '/' . $this->rest_base . '/me', array( 41 array( 42 'methods' => WP_REST_Server::READABLE, 43 'callback' => array( $this, 'get_current_item' ), 44 'permission_callback' => array( $this, 'get_current_item_permissions_check' ), 45 'args' => $this->get_item_params(), 46 ), 47 'schema' => array( $this, 'get_public_item_schema' ), 48 ) ); 49 } 50 51 /** 52 * Checks whether a given request has permission to read the current user's community events location. 53 * 54 * @since 4.8.0 55 * @access public 56 * 57 * @param WP_REST_Request $request Full details about the request. 58 * @return WP_Error|true True if the request has read access, WP_Error object otherwise. 59 */ 60 public function get_current_item_permissions_check( $request ) { 61 if ( ! is_user_logged_in() ) { 62 return new WP_Error( 'rest_not_logged_in', __( 'You are not currently logged in.' ), array( 'status' => 401 ) ); 63 } 64 65 return true; 66 } 67 68 /** 69 * Retrieves the community events location for the current user. 70 * 71 * @since 4.8.0 72 * @access public 73 * 74 * @param WP_REST_Request $request Full details about the request. 75 * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. 76 */ 77 public function get_current_item( $request ) { 78 require_once( ABSPATH . 'wp-admin/includes/class-wp-community-events.php' ); 79 80 $user_id = get_current_user_id(); 81 82 $location = $request->get_param( 'location' ); 83 $timezone = $request->get_param( 'timezone' ); 84 85 $saved_location = get_user_option( 'community-events-location', $user_id ); 86 $events_client = new WP_Community_Events( $user_id, $saved_location ); 87 $events = $events_client->get_events( $location, $timezone ); 88 89 $data = array(); 90 91 // Store the location network-wide, so the user doesn't have to set it on each site. 92 if ( ! is_wp_error( $events ) ) { 93 if ( isset( $events['location'] ) ) { 94 update_user_option( $user_id, 'community-events-location', $events['location'], true ); 95 96 $data = $this->prepare_item_for_response( $events['location'], $request ); 97 98 return rest_ensure_response( $data ); 99 } 100 } 101 102 return new WP_Error( 'rest_cannot_retrieve_user_location', __( 'The user location could not be retrieved.' ), array( 'status' => 503 ) ); 103 } 104 105 /** 106 * Prepares a single location output for response. 107 * 108 * @since 4.8.0 109 * @access public 110 * 111 * @param array $location Location data array from the API. 112 * @param WP_REST_Request $request Request object. 113 * @return WP_REST_Response Response object. 114 */ 115 public function prepare_item_for_response( $location, $request ) { 116 $data = array( 117 'description' => isset( $location['description'] ) ? $location['description'] : null, 118 'country' => isset( $location['country'] ) ? $location['country'] : null, 119 'latitude' => isset( $location['latitude'] ) ? (float) $location['latitude'] : null, 120 'longitude' => isset( $location['longitude'] ) ? (float) $location['longitude'] : null, 121 ); 122 123 $response = rest_ensure_response( $data ); 124 125 $url = rest_url( 'wp/dashboard/v1/community-events/events/me' ); 126 127 $url_args = array(); 128 129 if ( ! empty( $request['location'] ) ) { 130 $url_args['location'] = $request['location']; 131 } 132 if ( ! empty( $request['timezone'] ) ) { 133 $url_args['timezone'] = $request['timezone']; 134 } 135 136 if ( ! empty( $url_args ) ) { 137 $url = add_query_arg( $url_args, $url ); 138 } 139 140 $response->add_links( array( 141 'events' => array( 142 'href' => $url, 143 'embeddable' => true, 144 ), 145 ) ); 146 147 return $response; 148 } 149 150 /** 151 * Retrieves a community events location schema, conforming to JSON Schema. 152 * 153 * @since 4.8.0 154 * @access public 155 * 156 * @return array Item schema data. 157 */ 158 public function get_item_schema() { 159 return array( 160 '$schema' => 'http://json-schema.org/schema#', 161 'title' => 'community_events_location', 162 'type' => 'object', 163 'properties' => array( 164 'description' => array( 165 'description' => __( 'Location description.' ), 166 'type' => 'string', 167 'context' => array( 'view', 'edit', 'embed' ), 168 'readonly' => true, 169 ), 170 'country' => array( 171 'description' => __( 'Two-letter country code.' ), 172 'type' => 'string', 173 'context' => array( 'view', 'edit', 'embed' ), 174 'readonly' => true, 175 ), 176 'latitude' => array( 177 'description' => __( 'Latitude.' ), 178 'type' => 'number', 179 'context' => array( 'view', 'edit', 'embed' ), 180 'readonly' => true, 181 ), 182 'longitude' => array( 183 'description' => __( 'Longitude.' ), 184 'type' => 'number', 185 'context' => array( 'view', 'edit', 'embed' ), 186 'readonly' => true, 187 ), 188 ), 189 ); 190 } 191 192 /** 193 * Retrieves the params for a single item. 194 * 195 * @since 4.8.0 196 * @access public 197 * 198 * @return array Item parameters. 199 */ 200 public function get_item_params() { 201 return array( 202 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 203 'location' => array( 204 'description' => __( 'Optional city name to help determine the location.' ), 205 'type' => 'string', 206 'default' => '', 207 ), 208 'timezone' => array( 209 'description' => __( 'Optional timezone to help determine the location.' ), 210 'type' => 'string', 211 'default' => '', 212 ), 213 ); 214 } 215 } -
src/wp-includes/rest-api.php
237 237 // Settings. 238 238 $controller = new WP_REST_Settings_Controller; 239 239 $controller->register_routes(); 240 241 // Community events. 242 $controller = new WP_REST_Community_Events_Events_Controller; 243 $controller->register_routes(); 244 245 // Community events location. 246 $controller = new WP_REST_Community_Events_Location_Controller; 247 $controller->register_routes(); 240 248 } 241 249 242 250 /** -
src/wp-settings.php
234 234 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-users-controller.php' ); 235 235 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-comments-controller.php' ); 236 236 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-settings-controller.php' ); 237 require( ABSPATH . WPINC . '/rest-api/endpoints/dashboard/class-wp-rest-community-events-events-controller.php' ); 238 require( ABSPATH . WPINC . '/rest-api/endpoints/dashboard/class-wp-rest-community-events-location-controller.php' ); 237 239 require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-meta-fields.php' ); 238 240 require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-comment-meta-fields.php' ); 239 241 require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-post-meta-fields.php' );