From 7a9ce6d03fcd854b13382942fb020543c2d93e9c Mon Sep 17 00:00:00 2001 From: Andrew Ozz Date: Fri, 19 May 2017 05:48:42 +0000 Subject: [PATCH] Dashboard: Improve the handling of locations determined by geolocating the IP address and by entering a city name. Fix couple of edge cases, and some names. Props iandunn coreymckrill. Fixes #40702. Built from https://develop.svn.wordpress.org/trunk@40790 git-svn-id: http://core.svn.wordpress.org/trunk@40648 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/includes/ajax-actions.php | 23 +++++- .../includes/class-wp-community-events.php | 74 +++++++++++++++---- wp-admin/includes/dashboard.php | 22 ++++-- wp-admin/js/dashboard.js | 23 +++++- wp-admin/js/dashboard.min.js | 2 +- wp-includes/script-loader.php | 22 +++++- wp-includes/version.php | 2 +- 7 files changed, 139 insertions(+), 29 deletions(-) diff --git a/wp-admin/includes/ajax-actions.php b/wp-admin/includes/ajax-actions.php index a2e829bf65..e132ac8101 100644 --- a/wp-admin/includes/ajax-actions.php +++ b/wp-admin/includes/ajax-actions.php @@ -312,14 +312,33 @@ function wp_ajax_get_community_events() { $saved_location = get_user_option( 'community-events-location', $user_id ); $events_client = new WP_Community_Events( $user_id, $saved_location ); $events = $events_client->get_events( $search, $timezone ); + $ip_changed = false; if ( is_wp_error( $events ) ) { wp_send_json_error( array( 'error' => $events->get_error_message(), ) ); } else { - if ( isset( $events['location'] ) ) { - // Store the location network-wide, so the user doesn't have to set it on each site. + if ( empty( $saved_location['ip'] ) && ! empty( $events['location']['ip'] ) ) { + $ip_changed = true; + } elseif ( isset( $saved_location['ip'] ) && ! empty( $events['location']['ip'] ) && $saved_location['ip'] !== $events['location']['ip'] ) { + $ip_changed = true; + } + + /* + * The location should only be updated when it changes. The API doesn't always return + * a full location; sometimes it's missing the description or country. The location + * that was saved during the initial request is known to be good and complete, though. + * It should be left in tact until the user explicitly changes it (either by manually + * searching for a new location, or by changing their IP address). + * + * If the location were updated with an incomplete response from the API, then it could + * break assumptions that the UI makes (e.g., that there will always be a description + * that corresponds to a latitude/longitude location). + * + * The location is stored network-wide, so that the user doesn't have to set it on each site. + */ + if ( $ip_changed || $search ) { update_user_option( $user_id, 'community-events-location', $events['location'], true ); } diff --git a/wp-admin/includes/class-wp-community-events.php b/wp-admin/includes/class-wp-community-events.php index e27e731fff..9a41459740 100644 --- a/wp-admin/includes/class-wp-community-events.php +++ b/wp-admin/includes/class-wp-community-events.php @@ -94,12 +94,13 @@ class WP_Community_Events { return $cached_events; } - $request_url = $this->get_request_url( $location_search, $timezone ); - $response = wp_remote_get( $request_url ); + $api_url = 'https://api.wordpress.org/events/1.0/'; + $request_args = $this->get_request_args( $location_search, $timezone ); + $response = wp_remote_get( $api_url, $request_args ); $response_code = wp_remote_retrieve_response_code( $response ); $response_body = json_decode( wp_remote_retrieve_body( $response ), true ); $response_error = null; - $debugging_info = compact( 'request_url', 'response_code', 'response_body' ); + $debugging_info = compact( 'api_url', 'request_args', 'response_code', 'response_body' ); if ( is_wp_error( $response ) ) { $response_error = $response; @@ -128,6 +129,31 @@ class WP_Community_Events { unset( $response_body['ttl'] ); } + /* + * The IP in the response is usually the same as the one that was sent + * in the request, but in some cases it is different. In those cases, + * it's important to reset it back to the IP from the request. + * + * For example, if the IP sent in the request is private (e.g., 192.168.1.100), + * then the API will ignore that and use the corresponding public IP instead, + * and the public IP will get returned. If the public IP were saved, though, + * then get_cached_events() would always return `false`, because the transient + * would be generated based on the public IP when saving the cache, but generated + * based on the private IP when retrieving the cache. + */ + if ( ! empty( $response_body['location']['ip'] ) ) { + $response_body['location']['ip'] = $request_args['body']['ip']; + } + + /* + * The API doesn't return a description for latitude/longitude requests, + * but the description is already saved in the user location, so that + * one can be used instead. + */ + if ( $this->coordinates_match( $request_args['body'], $response_body['location'] ) && empty( $response_body['location']['description'] ) ) { + $response_body['location']['description'] = $this->user_location['description']; + } + $this->cache_events( $response_body, $expiration ); $response_body = $this->trim_events( $response_body ); @@ -143,24 +169,23 @@ class WP_Community_Events { } /** - * Builds a URL for requests to the w.org Events API. + * Builds an array of args to use in an HTTP request to the w.org Events API. * * @access protected * @since 4.8.0 * * @param string $search Optional. City search string. Default empty string. * @param string $timezone Optional. Timezone string. Default empty string. - * @return string The request URL. + * @return @return array The request args. */ - protected function get_request_url( $search = '', $timezone = '' ) { - $api_url = 'https://api.wordpress.org/events/1.0/'; - $args = array( + protected function get_request_args( $search = '', $timezone = '' ) { + $args = array( 'number' => 5, // Get more than three in case some get trimmed out. - 'ip' => $this->get_client_ip(), + 'ip' => self::get_unsafe_client_ip(), ); /* - * Send the minimal set of necessary arguments, in order to increase the + * Include the minimal set of necessary arguments, in order to increase the * chances of a cache-hit on the API side. */ if ( empty( $search ) && isset( $this->user_location['latitude'], $this->user_location['longitude'] ) ) { @@ -178,7 +203,10 @@ class WP_Community_Events { } } - return add_query_arg( $args, $api_url ); + // Wrap the args in an array compatible with the second parameter of `wp_remote_get()`. + return array( + 'body' => $args + ); } /** @@ -207,7 +235,7 @@ class WP_Community_Events { * @return false|string The anonymized address on success; the given address * or false on failure. */ - protected function get_client_ip() { + public static function get_unsafe_client_ip() { $client_ip = false; // In order of preference, with the best ones for this purpose first. @@ -249,6 +277,24 @@ class WP_Community_Events { return $client_ip; } + /** + * Test if two pairs of latitude/longitude coordinates match each other. + * + * @since 4.8.0 + * @access protected + * + * @param array $a The first pair, with indexes 'latitude' and 'longitude'. + * @param array $b The second pair, with indexes 'latitude' and 'longitude'. + * @return bool True if they match, false if they don't. + */ + protected function coordinates_match( $a, $b ) { + if ( ! isset( $a['latitude'], $a['longitude'], $b['latitude'], $b['longitude'] ) ) { + return false; + } + + return $a['latitude'] === $b['latitude'] && $a['longitude'] === $b['longitude']; + } + /** * Generates a transient key based on user location. * @@ -266,7 +312,9 @@ class WP_Community_Events { protected function get_events_transient_key( $location ) { $key = false; - if ( isset( $location['latitude'], $location['longitude'] ) ) { + if ( isset( $location['ip'] ) ) { + $key = 'community-events-' . md5( $location['ip'] ); + } else if ( isset( $location['latitude'], $location['longitude'] ) ) { $key = 'community-events-' . md5( $location['latitude'] . $location['longitude'] ); } diff --git a/wp-admin/includes/dashboard.php b/wp-admin/includes/dashboard.php index 274935105e..124dea2206 100644 --- a/wp-admin/includes/dashboard.php +++ b/wp-admin/includes/dashboard.php @@ -1234,15 +1234,23 @@ function wp_print_community_events_templates() { - ');var b=a(".quick-draft-textarea-clone"),c=a("#content"),d=c.height(),e=a(window).height()-100;b.css({"font-family":c.css("font-family"),"font-size":c.css("font-size"),"line-height":c.css("line-height"),"padding-bottom":c.css("paddingBottom"),"padding-left":c.css("paddingLeft"),"padding-right":c.css("paddingRight"),"padding-top":c.css("paddingTop"),"white-space":"pre-wrap","word-wrap":"break-word",display:"none"}),c.on("focus input propertychange",function(){var f=a(this),g=f.val()+" ",h=b.css("width",f.css("width")).text(g).outerHeight()+2;c.css("overflow-y","auto"),h===d||h>=e&&d>=e||(d=h>e?e:h,c.css("overflow","hidden"),f.css("height",d+"px"))})}}var c,d=a("#welcome-panel"),e=a("#wp_welcome_panel-hide");c=function(b){a.post(ajaxurl,{action:"update-welcome-panel",visible:b,welcomepanelnonce:a("#welcomepanelnonce").val()})},d.hasClass("hidden")&&e.prop("checked")&&d.removeClass("hidden"),a(".welcome-panel-close, .welcome-panel-dismiss a",d).click(function(b){b.preventDefault(),d.addClass("hidden"),c(0),a("#wp_welcome_panel-hide").prop("checked",!1)}),e.click(function(){d.toggleClass("hidden",!this.checked),c(this.checked?1:0)}),ajaxWidgets=["dashboard_primary"],ajaxPopulateWidgets=function(b){function c(b,c){var d,e=a("#"+c+" div.inside:visible").find(".widget-loading");e.length&&(d=e.parent(),setTimeout(function(){d.load(ajaxurl+"?action=dashboard-widgets&widget="+c+"&pagenow="+pagenow,"",function(){d.hide().slideDown("normal",function(){a(this).css("display","")})})},500*b))}b?(b=b.toString(),a.inArray(b,ajaxWidgets)!==-1&&c(0,b)):a.each(ajaxWidgets,c)},ajaxPopulateWidgets(),postboxes.add_postbox_toggles(pagenow,{pbshow:ajaxPopulateWidgets}),quickPressLoad=function(){var c,d=a("#quickpost-action");a('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop("disabled",!1),c=a("#quick-press").submit(function(b){function d(){var b=a(".drafts ul li").first();b.css("background","#fffbe5"),setTimeout(function(){b.css("background","none")},1e3)}b.preventDefault(),a("#dashboard_quick_press #publishing-action .spinner").show(),a('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop("disabled",!0),a.post(c.attr("action"),c.serializeArray(),function(b){a("#dashboard_quick_press .inside").html(b),a("#quick-press").removeClass("initial-form"),quickPressLoad(),d(),a("#title").focus()})}),a("#publish").click(function(){d.val("post-quickpress-publish")}),a("#title, #tags-input, #content").each(function(){var b=a(this),c=a("#"+this.id+"-prompt-text");""===this.value&&c.removeClass("screen-reader-text"),c.click(function(){a(this).addClass("screen-reader-text"),b.focus()}),b.blur(function(){""===this.value&&c.removeClass("screen-reader-text")}),b.focus(function(){c.addClass("screen-reader-text")})}),a("#quick-press").on("click focusin",function(){wpActiveEditor="content"}),b()},quickPressLoad(),a(".meta-box-sortables").sortable("option","containment","#wpwrap")}),jQuery(function(a){"use strict";var b,c=window.communityEventsData||{};b=window.wp.communityEvents={initialized:!1,model:null,init:function(){if(!b.initialized){var d=a("#community-events");a(".community-events-errors").attr("aria-hidden","true").removeClass("hide-if-js"),d.on("click",".community-events-toggle-location, .community-events-cancel",b.toggleLocationForm),d.on("submit",".community-events-form",function(c){c.preventDefault(),b.getEvents({location:a("#community-events-location").val()})}),c&&c.cache&&c.cache.location&&c.cache.events?b.renderEventsTemplate(c.cache,"app"):b.getEvents(),b.initialized=!0}},toggleLocationForm:function(b){var c=a(".community-events-toggle-location"),d=a(".community-events-cancel"),e=a(".community-events-form"),f=a();"object"==typeof b&&(f=a(b.target),b="true"==c.attr("aria-expanded")?"hide":"show"),"hide"===b?(c.attr("aria-expanded","false"),d.attr("aria-expanded","false"),e.attr("aria-hidden","true"),f.hasClass("community-events-cancel")&&c.focus()):(c.attr("aria-expanded","true"),d.attr("aria-expanded","true"),e.attr("aria-hidden","false"))},getEvents:function(b){var d,e=this,f=a(".community-events-form").children(".spinner");b=b||{},b._wpnonce=c.nonce,b.timezone=window.Intl?window.Intl.DateTimeFormat().resolvedOptions().timeZone:"",d=b.location?"user":"app",f.addClass("is-active"),wp.ajax.post("get-community-events",b).always(function(){f.removeClass("is-active")}).done(function(a){"no_location_available"===a.error&&(b.location?a.unknownCity=b.location:delete a.error),e.renderEventsTemplate(a,d)}).fail(function(){e.renderEventsTemplate({location:!1,error:!0},d)})},renderEventsTemplate:function(d,e){var f,g,h=/%(?:\d\$)?s/g,i=a(".community-events-toggle-location"),j=a("#community-events-location-message"),k=a(".community-events-results");g={".community-events":!0,".community-events-loading":!1,".community-events-errors":!1,".community-events-error-occurred":!1,".community-events-could-not-locate":!1,"#community-events-location-message":!1,".community-events-toggle-location":!1,".community-events-results":!1},d.location?(f=wp.template("community-events-attend-event-near"),j.html(f(d)),d.events.length?(f=wp.template("community-events-event-list"),k.html(f(d))):(f=wp.template("community-events-no-upcoming-events"),k.html(f(d))),wp.a11y.speak(c.l10n.city_updated.replace(h,d.location.description),"assertive"),g["#community-events-location-message"]=!0,g[".community-events-toggle-location"]=!0,g[".community-events-results"]=!0):d.unknownCity?(f=wp.template("community-events-could-not-locate"),a(".community-events-could-not-locate").html(f(d)),wp.a11y.speak(c.l10n.could_not_locate_city.replace(h,d.unknownCity)),g[".community-events-errors"]=!0,g[".community-events-could-not-locate"]=!0):d.error&&"user"===e?(wp.a11y.speak(c.l10n.error_occurred_please_try_again),g[".community-events-errors"]=!0,g[".community-events-error-occurred"]=!0):(j.text(c.l10n.enter_closest_city),g["#community-events-location-message"]=!0,g[".community-events-toggle-location"]=!0),_.each(g,function(b,c){a(c).attr("aria-hidden",!b)}),i.attr("aria-expanded",g[".community-events-toggle-location"]),d.location?(b.toggleLocationForm("hide"),"user"===e&&i.focus()):b.toggleLocationForm("show")}},a("#dashboard_primary").is(":visible")?b.init():a(document).on("postbox-toggled",function(c,d){var e=a(d);"dashboard_primary"===e.attr("id")&&e.is(":visible")&&b.init()})}); \ No newline at end of file +var ajaxWidgets,ajaxPopulateWidgets,quickPressLoad;window.wp=window.wp||{},jQuery(document).ready(function(a){function b(){if(!(document.documentMode&&document.documentMode<9)){a("body").append('');var b=a(".quick-draft-textarea-clone"),c=a("#content"),d=c.height(),e=a(window).height()-100;b.css({"font-family":c.css("font-family"),"font-size":c.css("font-size"),"line-height":c.css("line-height"),"padding-bottom":c.css("paddingBottom"),"padding-left":c.css("paddingLeft"),"padding-right":c.css("paddingRight"),"padding-top":c.css("paddingTop"),"white-space":"pre-wrap","word-wrap":"break-word",display:"none"}),c.on("focus input propertychange",function(){var f=a(this),g=f.val()+" ",h=b.css("width",f.css("width")).text(g).outerHeight()+2;c.css("overflow-y","auto"),h===d||h>=e&&d>=e||(d=h>e?e:h,c.css("overflow","hidden"),f.css("height",d+"px"))})}}var c,d=a("#welcome-panel"),e=a("#wp_welcome_panel-hide");c=function(b){a.post(ajaxurl,{action:"update-welcome-panel",visible:b,welcomepanelnonce:a("#welcomepanelnonce").val()})},d.hasClass("hidden")&&e.prop("checked")&&d.removeClass("hidden"),a(".welcome-panel-close, .welcome-panel-dismiss a",d).click(function(b){b.preventDefault(),d.addClass("hidden"),c(0),a("#wp_welcome_panel-hide").prop("checked",!1)}),e.click(function(){d.toggleClass("hidden",!this.checked),c(this.checked?1:0)}),ajaxWidgets=["dashboard_primary"],ajaxPopulateWidgets=function(b){function c(b,c){var d,e=a("#"+c+" div.inside:visible").find(".widget-loading");e.length&&(d=e.parent(),setTimeout(function(){d.load(ajaxurl+"?action=dashboard-widgets&widget="+c+"&pagenow="+pagenow,"",function(){d.hide().slideDown("normal",function(){a(this).css("display","")})})},500*b))}b?(b=b.toString(),a.inArray(b,ajaxWidgets)!==-1&&c(0,b)):a.each(ajaxWidgets,c)},ajaxPopulateWidgets(),postboxes.add_postbox_toggles(pagenow,{pbshow:ajaxPopulateWidgets}),quickPressLoad=function(){var c,d=a("#quickpost-action");a('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop("disabled",!1),c=a("#quick-press").submit(function(b){function d(){var b=a(".drafts ul li").first();b.css("background","#fffbe5"),setTimeout(function(){b.css("background","none")},1e3)}b.preventDefault(),a("#dashboard_quick_press #publishing-action .spinner").show(),a('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop("disabled",!0),a.post(c.attr("action"),c.serializeArray(),function(b){a("#dashboard_quick_press .inside").html(b),a("#quick-press").removeClass("initial-form"),quickPressLoad(),d(),a("#title").focus()})}),a("#publish").click(function(){d.val("post-quickpress-publish")}),a("#title, #tags-input, #content").each(function(){var b=a(this),c=a("#"+this.id+"-prompt-text");""===this.value&&c.removeClass("screen-reader-text"),c.click(function(){a(this).addClass("screen-reader-text"),b.focus()}),b.blur(function(){""===this.value&&c.removeClass("screen-reader-text")}),b.focus(function(){c.addClass("screen-reader-text")})}),a("#quick-press").on("click focusin",function(){wpActiveEditor="content"}),b()},quickPressLoad(),a(".meta-box-sortables").sortable("option","containment","#wpwrap")}),jQuery(function(a){"use strict";var b,c=window.communityEventsData||{};b=window.wp.communityEvents={initialized:!1,model:null,init:function(){if(!b.initialized){var d=a("#community-events");a(".community-events-errors").attr("aria-hidden","true").removeClass("hide-if-js"),d.on("click",".community-events-toggle-location, .community-events-cancel",b.toggleLocationForm),d.on("submit",".community-events-form",function(c){c.preventDefault(),b.getEvents({location:a("#community-events-location").val()})}),c&&c.cache&&c.cache.location&&c.cache.events?b.renderEventsTemplate(c.cache,"app"):b.getEvents(),b.initialized=!0}},toggleLocationForm:function(b){var c=a(".community-events-toggle-location"),d=a(".community-events-cancel"),e=a(".community-events-form"),f=a();"object"==typeof b&&(f=a(b.target),b="true"==c.attr("aria-expanded")?"hide":"show"),"hide"===b?(c.attr("aria-expanded","false"),d.attr("aria-expanded","false"),e.attr("aria-hidden","true"),f.hasClass("community-events-cancel")&&c.focus()):(c.attr("aria-expanded","true"),d.attr("aria-expanded","true"),e.attr("aria-hidden","false"))},getEvents:function(b){var d,e=this,f=a(".community-events-form").children(".spinner");b=b||{},b._wpnonce=c.nonce,b.timezone=window.Intl?window.Intl.DateTimeFormat().resolvedOptions().timeZone:"",d=b.location?"user":"app",f.addClass("is-active"),wp.ajax.post("get-community-events",b).always(function(){f.removeClass("is-active")}).done(function(a){"no_location_available"===a.error&&(b.location?a.unknownCity=b.location:delete a.error),e.renderEventsTemplate(a,d)}).fail(function(){e.renderEventsTemplate({location:!1,error:!0},d)})},renderEventsTemplate:function(d,e){var f,g,h=/%(?:\d\$)?s/g,i=a(".community-events-toggle-location"),j=a("#community-events-location-message"),k=a(".community-events-results");g={".community-events":!0,".community-events-loading":!1,".community-events-errors":!1,".community-events-error-occurred":!1,".community-events-could-not-locate":!1,"#community-events-location-message":!1,".community-events-toggle-location":!1,".community-events-results":!1},d.location.ip?(j.text(c.l10n.attend_event_near_generic),d.events.length?(f=wp.template("community-events-event-list"),k.html(f(d))):(f=wp.template("community-events-no-upcoming-events"),k.html(f(d))),g["#community-events-location-message"]=!0,g[".community-events-toggle-location"]=!0,g[".community-events-results"]=!0):d.location.description?(f=wp.template("community-events-attend-event-near"),j.html(f(d)),d.events.length?(f=wp.template("community-events-event-list"),k.html(f(d))):(f=wp.template("community-events-no-upcoming-events"),k.html(f(d))),wp.a11y.speak(c.l10n.city_updated.replace(h,d.location.description),"assertive"),g["#community-events-location-message"]=!0,g[".community-events-toggle-location"]=!0,g[".community-events-results"]=!0):d.unknownCity?(f=wp.template("community-events-could-not-locate"),a(".community-events-could-not-locate").html(f(d)),wp.a11y.speak(c.l10n.could_not_locate_city.replace(h,d.unknownCity)),g[".community-events-errors"]=!0,g[".community-events-could-not-locate"]=!0):d.error&&"user"===e?(wp.a11y.speak(c.l10n.error_occurred_please_try_again),g[".community-events-errors"]=!0,g[".community-events-error-occurred"]=!0):(j.text(c.l10n.enter_closest_city),g["#community-events-location-message"]=!0,g[".community-events-toggle-location"]=!0),_.each(g,function(b,c){a(c).attr("aria-hidden",!b)}),i.attr("aria-expanded",g[".community-events-toggle-location"]),d.location&&(d.location.ip||d.location.latitude)?(b.toggleLocationForm("hide"),"user"===e&&i.focus()):b.toggleLocationForm("show")}},a("#dashboard_primary").is(":visible")?b.init():a(document).on("postbox-toggled",function(c,d){var e=a(d);"dashboard_primary"===e.attr("id")&&e.is(":visible")&&b.init()})}); \ No newline at end of file diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php index 5dad398001..ff7d8bb855 100644 --- a/wp-includes/script-loader.php +++ b/wp-includes/script-loader.php @@ -1012,9 +1012,24 @@ function wp_localize_community_events() { require_once( ABSPATH . 'wp-admin/includes/class-wp-community-events.php' ); - $user_id = get_current_user_id(); - $user_location = get_user_option( 'community-events-location', $user_id ); - $events_client = new WP_Community_Events( $user_id, $user_location ); + $user_id = get_current_user_id(); + $saved_location = get_user_option( 'community-events-location', $user_id ); + $saved_ip_address = isset( $saved_location['ip'] ) ? $saved_location['ip'] : false; + $current_ip_address = WP_Community_Events::get_unsafe_client_ip(); + + /* + * If the user's location is based on their IP address, then update their + * location when their IP address changes. This allows them to see events + * in their current city when travelling. Otherwise, they would always be + * shown events in the city where they were when they first loaded the + * Dashboard, which could have been months or years ago. + */ + if ( $saved_ip_address && $current_ip_address && $current_ip_address !== $saved_ip_address ) { + $saved_location['ip'] = $current_ip_address; + update_user_option( $user_id, 'community-events-location', $saved_location, true ); + } + + $events_client = new WP_Community_Events( $user_id, $saved_location ); wp_localize_script( 'dashboard', 'communityEventsData', array( 'nonce' => wp_create_nonce( 'community_events' ), @@ -1023,6 +1038,7 @@ function wp_localize_community_events() { 'l10n' => array( 'enter_closest_city' => __( 'Enter your closest city to find nearby events.' ), 'error_occurred_please_try_again' => __( 'An error occurred. Please try again.' ), + 'attend_event_near_generic' => __( 'Attend an upcoming event near you.' ), /* * These specific examples were chosen to highlight the fact that a diff --git a/wp-includes/version.php b/wp-includes/version.php index 3ab4171a41..9eabf9d10d 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.8-beta1-40789'; +$wp_version = '4.8-beta1-40790'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.