'manage_pcwp_events'); add_action('enqueue_block_editor_assets', [$this, 'editor']); add_action('admin_enqueue_scripts', [$this, 'classicAssets']); add_action('add_meta_boxes', [$this, 'metaBoxes']); add_action('save_post', [$this, 'saveClassic'], 15, 2); foreach (['added_post_meta', 'updated_post_meta', 'deleted_post_meta'] as $hook) { add_action($hook, [$this, 'venueChanged'], 30, 4); } add_action('transition_post_status', [$this, 'venueStatus'], 30, 3); add_action('before_delete_post', function (int $id): void { if (get_post_type($id) === 'pcwp_venue') { $this->queue($id); } }); add_filter('cron_schedules', static function (array $schedules): array { $schedules['pcwp_location_minute'] = ['interval' => 60, 'display' => 'Location projection refresh']; return $schedules; }); add_action('pcwp_refresh_locations', [$this, 'refresh']); } public function assets(): void { register_post_meta('pcwp_venue', Location::KEY, array_merge(['single' => true, 'auth_callback' => static fn (bool $allowed, string $key, int $id): bool => current_user_can('edit_post', $id)], Location::definition())); $asset = is_readable(PCWP_PATH . 'build/map-view.asset.php') ? include PCWP_PATH . 'build/map-view.asset.php' : ['dependencies' => [], 'version' => PCWP_VERSION]; wp_register_script('pcwp-map-view', PCWP_URL . 'build/map-view.js', $asset['dependencies'], $asset['version'], true); wp_register_style('pcwp-map-view', PCWP_URL . 'build/map-view.css', [], $asset['version']); wp_register_style('pcwp-location', PCWP_URL . 'assets/location.css', [], (string) filemtime(PCWP_PATH . 'assets/location.css')); wp_localize_script('pcwp-map-view', 'pcwpMapSettings', [ 'styles' => MapSettings::styles(), 'workerUrl' => PCWP_URL . 'build/maplibre-gl-worker.mjs', ]); wp_register_script('pcwp-map-block', PCWP_URL . 'assets/map-block.js', ['pcwp-block-styling', 'pcwp-map-view', 'wp-blocks', 'wp-block-editor', 'wp-components', 'wp-element', 'wp-data', 'wp-api-fetch', 'wp-i18n'], (string) filemtime(PCWP_PATH . 'assets/map-block.js'), true); register_block_type(PCWP_PATH . 'blocks/event-map', ['render_callback' => [MapBlock::class, 'render']]); } public function editor(): void { if (in_array(get_current_screen()?->post_type, ['pcwp_event', 'pcwp_series', 'pcwp_venue'], true)) { $this->locationAssets(); } } public function classicAssets(): void { $screen = get_current_screen(); if ($screen !== null && in_array($screen->post_type, ['pcwp_event', 'pcwp_venue', 'pcwp_series'], true) && ! $screen->is_block_editor()) { $this->locationAssets(); } } private function locationAssets(): void { wp_enqueue_script('pcwp-location-editor', PCWP_URL . 'assets/location-editor.js', ['pcwp-map-view', 'wp-components', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins', 'wp-api-fetch', 'wp-dom-ready'], (string) filemtime(PCWP_PATH . 'assets/location-editor.js'), true); wp_localize_script('pcwp-location-editor', 'pcwpLocationSettings', ['enabled' => get_option('pcwp_geocoding_provider') === 'geoapify' && GeocodingKey::get() !== '', 'language' => substr(get_user_locale(), 0, 2)]); wp_enqueue_style('wp-components'); wp_enqueue_style('pcwp-map-view'); wp_enqueue_style('pcwp-location'); } public function metaBoxes(): void { if (get_current_screen()?->is_block_editor()) { return; } foreach (['pcwp_event', 'pcwp_venue', 'pcwp_series'] as $type) { add_meta_box('pcwp_location', __('Location', 'proeventswp'), [$this, 'classic'], $type, 'normal'); } } public function classic(\WP_Post $post): void { wp_nonce_field('pcwp_location_' . $post->ID, 'pcwp_location_nonce'); echo '
'; echo ''; echo ''; } public function saveClassic(int $id, \WP_Post $post): void { if (! in_array($post->post_type, ['pcwp_event', 'pcwp_venue', 'pcwp_series'], true) || wp_is_post_revision($id) || wp_is_post_autosave($id) || ! current_user_can('edit_post', $id)) { return; } if (isset($_POST['pcwp_location_nonce'], $_POST['pcwp_location_json']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['pcwp_location_nonce'])), 'pcwp_location_' . $id)) { update_post_meta($id, Location::KEY, wp_slash(Location::normalize(wp_unslash((string) $_POST['pcwp_location_json'])))); } } /** @param int|list $metaId */ public function venueChanged(int|array $metaId, int $id, string $key, mixed $value): void { unset($metaId, $value); if (get_post_type($id) === 'pcwp_venue' && in_array($key, [Location::KEY, '_pcwp_latitude', '_pcwp_longitude'], true)) { $this->queue($id); } } public function venueStatus(string $new, string $old, \WP_Post $post): void { if ($new !== $old && $post->post_type === 'pcwp_venue') { $this->queue($post->ID); } } private function queue(int $venueId): void { $queue = (array) get_option('pcwp_location_queue', []); $queue[$venueId] = ['cursor' => 0, 'revision' => wp_generate_uuid4()]; update_option('pcwp_location_queue', $queue, false); if (! wp_next_scheduled('pcwp_refresh_locations')) { wp_schedule_event(time() + 10, 'pcwp_location_minute', 'pcwp_refresh_locations'); } } public function refresh(): void { global $wpdb; $queue = (array) get_option('pcwp_location_queue', []); if ($queue === []) { wp_clear_scheduled_hook('pcwp_refresh_locations'); return; } $venueId = (int) array_key_first($queue); $job = $queue[$venueId]; $ids = $wpdb->get_col($wpdb->prepare("SELECT event_id FROM {$wpdb->prefix}pcwp_event_entities WHERE entity_type='venue' AND entity_id=%d AND event_id>%d ORDER BY event_id LIMIT 100", $venueId, $job['cursor'])); foreach ($ids as $id) { $location = Location::resolve((int) $id); $saved = $wpdb->query($wpdb->prepare("UPDATE {$wpdb->prefix}pcwp_occurrences SET latitude=NULLIF(%s,''),longitude=NULLIF(%s,'') WHERE event_id=%d", $location['latitude'] === null ? '' : (string) $location['latitude'], $location['longitude'] === null ? '' : (string) $location['longitude'], $id)); if ($saved === false) { return; // Keep the checkpoint; the recurring job retries this batch. } WpEventRepository::clearEventCache((int) $id); } $latest = (array) get_option('pcwp_location_queue', []); if (($latest[$venueId]['revision'] ?? '') === $job['revision']) { if (count($ids) < 100) { unset($latest[$venueId]); } else { $latest[$venueId]['cursor'] = (int) end($ids); } update_option('pcwp_location_queue', $latest, false); } } }