diff --git a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/events-landing-page.php b/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/events-landing-page.php deleted file mode 100644 index 3878b30f57..0000000000 --- a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/events-landing-page.php +++ /dev/null @@ -1,54 +0,0 @@ - __NAMESPACE__ . '\render_events_landing_page', - ) - ); -} - -/** - * Render the output of the Events Landing Page block. - */ -function render_events_landing_page( array $block_attributes, string $content ): string { - switch ( $block_attributes['events'] ) { - case 'all-upcoming': - $map_options = array( - 'id' => 'all-upcoming-events', - 'markers' => get_all_upcoming_events(), - ); - break; - - case 'city': - // Can't use `$wp->request` because Gutenberg calls this on `init`, before `parse_request`. - // @todo That was true when this was part of a pattern, but it isn't now that this is a block. We can - // maybe pass `$wp->request` to `normalize_request_uri()` now, or maybe remove that function entirely. - $request_uri = normalize_request_uri( $_SERVER['REQUEST_URI'], $_SERVER['QUERY_STRING'] ); - - $map_options = array( - 'id' => 'city-landing-page', - 'markers' => get_city_landing_page_events( $request_uri ), - ); - break; - - default: - return 'No events available'; - } - - $map_options['apiKey'] = 'production' === wp_get_environment_type() ? 'WORDCAMP_PROD_GOOGLE_MAPS_API_KEY' : 'WORDCAMP_DEV_GOOGLE_MAPS_API_KEY'; - - return do_blocks( '' ); -} diff --git a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/package.json b/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/package.json deleted file mode 100644 index cd3ed74644..0000000000 --- a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "events-landing-page", - "version": "0.0.1", - "description": "Gather events for the different landing pages, and pass them to the Google Map block to be displayed.", - "main": "index.js", - "scripts": { - "start": "wp-scripts start", - "build": "wp-scripts build" - }, - "devDependencies": { - "@wordpress/scripts": "^26.13.0" - } -} diff --git a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/src/block.json b/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/src/block.json deleted file mode 100644 index 40e0db2136..0000000000 --- a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/src/block.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://schemas.wp.org/trunk/block.json", - "apiVersion": 2, - "name": "wporg/events-landing-page", - "title": "Events Landing Page", - "icon": "admin-site-alt", - "category": "widgets", - "description": "Gather events for the different landing pages, and pass them to the Google Map block to be displayed.", - "textdomain": "wporg", - "attributes": { - "events": { - "type": "string", - "default": "" - } - }, - "editorScript": "file:./index.js" -} diff --git a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/src/index.js b/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/src/index.js deleted file mode 100644 index 57bc371958..0000000000 --- a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/src/index.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { registerBlockType } from '@wordpress/blocks'; -import { Placeholder } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import metadata from './block.json'; - -function Edit() { - return ( - - ); -} - -registerBlockType( metadata.name, { - edit: Edit, -} ); diff --git a/public_html/wp-content/themes/wporg-events-2023/functions.php b/public_html/wp-content/themes/wporg-events-2023/functions.php index cd747030ad..18187354bd 100644 --- a/public_html/wp-content/themes/wporg-events-2023/functions.php +++ b/public_html/wp-content/themes/wporg-events-2023/functions.php @@ -1,59 +1,13 @@ set_query_var( 'page', '' ); - $wp->set_query_var( 'pagename', 'city-landing-page' ); -} - -/** - * Determine if the current request is for a city landing page. - * - * See `get_city_landing_sites()` for examples of request URIs. - */ -function is_city_landing_page() { - global $wp, $wpdb; - - // The landing page formats will always match the rewrite rule for pages, which sets `page` and `pagename`. - if ( empty( $wp->query_vars['page'] ) && empty( $wp->query_vars['pagename'] ) ) { - return false; - } - - $city = explode( '/', $wp->request ); - $city = $city[0] ?? false; - - // Using this instead of `get_sites()` so that the search doesn't match false positives. - $sites = $wpdb->get_results( $wpdb->prepare( " - SELECT blog_id - FROM {$wpdb->blogs} - WHERE - site_id = %d AND - path REGEXP %s - LIMIT 1", - EVENTS_NETWORK_ID, - "^/$city/\d{4}/[a-z-]+/$" - ) ); - - return ! empty( $sites ); -} /** * Enqueue scripts and styles. diff --git a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/event-getters.php b/public_html/wp-content/themes/wporg-events-2023/inc/city-landing-pages.php similarity index 56% rename from public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/event-getters.php rename to public_html/wp-content/themes/wporg-events-2023/inc/city-landing-pages.php index 0e9240cfa3..7dabc38cf3 100644 --- a/public_html/wp-content/themes/wporg-events-2023/blocks/events-landing-page/event-getters.php +++ b/public_html/wp-content/themes/wporg-events-2023/inc/city-landing-pages.php @@ -1,14 +1,65 @@ set_query_var( 'page', '' ); + $wp->set_query_var( 'pagename', 'city-landing-page' ); +} + +/** + * Determine if the current request is for a city landing page. + * + * See `get_city_landing_sites()` for examples of request URIs. + */ +function is_city_landing_page(): bool { + global $wp, $wpdb; + + // The landing page formats will always match the rewrite rule for pages, which sets `page` and `pagename`. + if ( empty( $wp->query_vars['page'] ) && empty( $wp->query_vars['pagename'] ) ) { + return false; + } + + $city = explode( '/', $wp->request ); + $city = $city[0] ?? false; + + // Using this instead of `get_sites()` so that the search doesn't match false positives. + $sites = $wpdb->get_results( $wpdb->prepare( " + SELECT blog_id + FROM {$wpdb->blogs} + WHERE + site_id = %d AND + path REGEXP %s + LIMIT 1", + EVENTS_NETWORK_ID, + "^/$city/\d{4}/[a-z-]+/$" + ) ); + + return ! empty( $sites ); +} + /** * Schedule cron jobs. */ @@ -24,14 +75,30 @@ function schedule_cron_jobs(): void { * Without this, users would have to wait for new results to be generated every time the cache expires. That could * make the front end very slow. This will refresh the cache before it expires, so that the front end can always * load cached results. + * + * These pages can't use the cache-priming cron provided by the Event Filters plugin, because it doesn't know how + * to handle them. */ function prime_query_cache(): void { - get_all_upcoming_events( true ); - $city_landing_uris = get_known_city_landing_request_uris(); + // It won't know the "current" page in a cron context, so we'll pass it directly to `get_cache_key()` in the loop below. + remove_action( 'google_map_event_filters_cache_key_parts', __NAMESPACE__ .'\add_landing_page_to_cache_key' ); + foreach ( $city_landing_uris as $request_uri ) { - get_city_landing_page_events( $request_uri, true ); + // Must match the return value of the cache key that `Google_Map_Event_Filters\get_events()` generates during block rendering, + // including the `landing_page` item added by `add_landing_page_to_cache_key()`. + $parts = array( + 'filter_slug' => FILTER_SLUG, + 'start_timestamp' => 0, + 'end_timestamp' => 0, + 'landing_page' => $request_uri + ); + + $cache_key = Google_Map_Event_Filters\get_cache_key( $parts ); + $events = get_city_landing_page_events( $request_uri, true ); + + set_transient( $cache_key, $events, DAY_IN_SECONDS ); } } @@ -71,100 +138,19 @@ function get_known_city_landing_request_uris(): array { return array_keys( $city_landing_pages ); } -/** - * Query a table that's encoded with the `latin1` charset. - * - * Unlike wordpress.org, wordcamp.org has a `DB_CHARSET` of `utf8mb4`, so that's what WPDB uses when querying - * tables. w.org tables use `latin1`, so we need to switch to that when pulling from them. If you query it with - * `utf8mb4`, you'll get Mojibake. - * - * @param string $prepared_query ⚠️ This must have already be ran through `$wpdb->prepare()` if needed. - * - * @return object|null - */ -function get_latin1_results_with_prepared_query( string $prepared_query ) { - global $wpdb; - - // Local environments don't always use HyperDB, but production does. - $db_handle = $wpdb instanceof hyperdb ? $wpdb->db_connect( $prepared_query ) : $wpdb->dbh; - $wpdb->set_charset( $db_handle, 'latin1', 'latin1_swedish_ci' ); - - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- This function doesn't have the context to prepare it, the caller must. - $results = $wpdb->get_results( $prepared_query ); - - // Revert to the default charset to avoid affecting other queries. - $wpdb->set_charset( $db_handle, DB_CHARSET, DB_COLLATE ); - - return $results; -} - -/** - * Get a list of all upcoming events across all sites. - */ -function get_all_upcoming_events( bool $force_refresh = false ): array { - $cache_key = 'event_landing_all_upcoming_events'; - - if ( ! $force_refresh ) { - $cached_events = get_transient( $cache_key ); - - if ( $cached_events ) { - return $cached_events; - } - } - - $events = get_latin1_results_with_prepared_query( ' - SELECT - id, `type`, title, url, meetup, location, latitude, longitude, date_utc, - date_utc_offset AS tz_offset - FROM `wporg_events` - WHERE - status = "scheduled" AND - ( - ( "wordcamp" = type AND date_utc BETWEEN NOW() AND ADDDATE( NOW(), 180 ) ) OR - ( "meetup" = type AND date_utc BETWEEN NOW() AND ADDDATE( NOW(), 30 ) ) - ) - ORDER BY date_utc ASC - LIMIT 400' - ); - - foreach ( $events as $event ) { - // `capital_P_dangit()` won't work here because the current filter isn't `the_title` and there isn't a safelisted prefix before `$text`. - $event->title = str_replace( 'Wordpress', 'WordPress', $event->title ); - - // `date_utc` is a misnomer, the value is actually in the local timezone of the event. So, convert to a true Unix timestamp (UTC). - // Can't do this reliably in the query because MySQL converts it to the server timezone. - $event->timestamp = strtotime( $event->date_utc ) - $event->tz_offset; - - unset( $event->date_utc ); - } - - // `prime_query_cache()` should update this hourly, but expire after a day just in case it doesn't. - set_transient( $cache_key, $events, DAY_IN_SECONDS ); - - return $events; -} /** * Get events based on the given request URI. * * See `get_city_landing_sites()` for how request URIs map to events. */ -function get_city_landing_page_events( string $request_uri, bool $force_refresh = false ): array { - $limit = 300; - $cache_key = 'event_landing_city_events_' . md5( $request_uri ); +function get_city_landing_page_events( string $request_uri ): array { + $limit = 300; if ( empty( $request_uri ) || '/' === $request_uri ) { return array(); } - if ( ! $force_refresh ) { - $cached_events = get_transient( $cache_key ); - - if ( $cached_events ) { - return $cached_events; - } - } - $sites = get_city_landing_sites( $request_uri, $limit ); switch_to_blog( WORDCAMP_ROOT_BLOG_ID ); @@ -202,26 +188,9 @@ function get_city_landing_page_events( string $request_uri, bool $force_refresh restore_current_blog(); - // `prime_query_cache()` should update this hourly, but expire after a day just in case it doesn't find all the - // valid request URIs. - set_transient( $cache_key, $events, DAY_IN_SECONDS ); - return $events; } -/** - * Standardize request URIs so they can be reliably used as cache keys. - * - * For example, `/rome`, `/rome/` and `/rome/?foo=bar` should all be `/rome/`. - */ -function normalize_request_uri( $raw_uri, $query_string ) { - $clean_uri = str_replace( '?' . $query_string, '', $raw_uri ); - $clean_uri = trailingslashit( $clean_uri ); - $clean_uri = '/' . ltrim( $clean_uri, '/' ); - - return $clean_uri; -} - /** * Get sites that match the given request URI. * @@ -297,3 +266,51 @@ function get_wordcamp_offset( WP_Post $wordcamp ): int { return $wordcamp_timezone->getOffset( $wordcamp_datetime ); } + +/** + * Disable the cron job that Google Map Event Filters registers. + * + * This plugin needs to run its own cron to prime the events cache, because the upstream one doesn't know how to handle city pages. + */ +function disable_event_filters_cron( bool $enabled, string $filter_slug ): bool { + if ( FILTER_SLUG === $filter_slug ) { + $enabled = false; + } + + return $enabled; +} + +/** + * Get the events for the current city landing page. + */ +function get_events( array $events ): array { + if ( is_city_landing_page() ) { + $events = get_city_landing_page_events( get_current_landing_page() ); + } + + return $events; +} + +/** + * Get the path to the current landing page, with surrounding slashes. + */ +function get_current_landing_page(): string { + global $wp; + + $page = '/' . $wp->request . '/'; + + return $page; +} + +/** + * Adds the current landing page to the Event Filters cache key. + * + * Without this, all city pages would share the same cache key, and the wrong events would show up on most pages. + */ +function add_landing_page_to_cache_key( array $items ) : array { + if ( is_city_landing_page() && FILTER_SLUG === $items['filter_slug'] ) { + $items['landing_page'] = get_current_landing_page(); + } + + return $items; +} diff --git a/public_html/wp-content/themes/wporg-events-2023/parts/front-page/cover.html b/public_html/wp-content/themes/wporg-events-2023/parts/front-page/cover.html index 8751867bb1..f6a24c4635 100644 --- a/public_html/wp-content/themes/wporg-events-2023/parts/front-page/cover.html +++ b/public_html/wp-content/themes/wporg-events-2023/parts/front-page/cover.html @@ -25,8 +25,6 @@

Meet the community behind WordPress

- -

map goes here when block updated

- + \ No newline at end of file diff --git a/public_html/wp-content/themes/wporg-events-2023/parts/front-page/events.html b/public_html/wp-content/themes/wporg-events-2023/parts/front-page/events.html index 42e642fff0..3f19ef8d45 100644 --- a/public_html/wp-content/themes/wporg-events-2023/parts/front-page/events.html +++ b/public_html/wp-content/themes/wporg-events-2023/parts/front-page/events.html @@ -5,7 +5,7 @@

Upcoming Events

- +
diff --git a/public_html/wp-content/themes/wporg-events-2023/templates/page-city-landing-page.html b/public_html/wp-content/themes/wporg-events-2023/templates/page-city-landing-page.html index c4f989270e..463e87579b 100644 --- a/public_html/wp-content/themes/wporg-events-2023/templates/page-city-landing-page.html +++ b/public_html/wp-content/themes/wporg-events-2023/templates/page-city-landing-page.html @@ -2,7 +2,7 @@
- +