Skip to content

This is part of Build log, a running series on the WordPress plugins I maintain for venue and community sites.

All events have to happen at a venue – Obviously! How the venues are managed is actually a really large part of this plugin.

If a venue is putting on five gigs a year in the same hall, nobody wants to type that hall’s address, postcode and “yes, there’s a step at the front door” note five separate times. So venues got their own home in the plugin: a proper post type sitting quietly behind the scenes, with a name, an address, a pin on a map, whether it’s indoor or outdoor — or both, for a beer garden with a covered stage — and whether there’s step-free access.

On the event edit screen you get a dropdown of every venue ever saved. Pick one and a summary appears immediately, without a page reload: address, access notes, the lot. You can check you’ve got the right hall before you commit to anything, which matters more than it sounds when a venue has three rooms with similar names.

If the venue is new, you’re not sent off to a separate screen to create it and then sent back to start the event again. You fill the details in on the event itself, tick save this as a venue I can reuse, and it’s in the dropdown from then on.

The map is Leaflet with a geocoder control, bundled with the plugin rather than pulled from a CDN, and chosen over the obvious alternative (Google Maps) for the unglamorous reason that it’s free! A Google Maps key is one more thing to create per client, one more thing to bill for, and one more thing to quietly expire two years later and drop a “for development purposes only” watermark across a village hall’s contact page.

A reference, not a copy

The decision underneath all of that is what an event actually stores. Once a venue is saved, an event holds a single piece of metadata — _scem_venue_id — and reads everything else through it at render time.

The payoff is immediate. Move the venue two doors down, or finally add the postcode nobody typed properly the first time, and every event using it updates at once. Nobody has to go around correcting twelve listings by hand, and no listing is quietly still showing last year’s address because whoever fixed the others got bored.

Which leaves an obvious question, and it’s the one that took the actual thought: what happens when someone deletes a venue that events are still pointing at?

Not every event wants a saved venue either. A one-off in a field fill the location fields in directly and never touch the venue list. Both paths share one set of field definitions, so a one-off location and a saved venue store identical metadata under identical keys.

How did I deal with these?

The moment before it goes

Do nothing and you get the worst outcome available — a dozen events pointing at an ID that no longer resolves, rendering a location block with nothing in it. Silently, on the public site, at whatever point someone tidied up the admin.

Blocking the deletion is the other obvious option and it’s not much better; now the venue list is a graveyard you can’t clear, and someone will eventually delete the events instead to get rid of the venue.

So the plugin hooks the last possible moment before deletion and takes a snapshot:

add_action('before_delete_post', [$this, 'detachFromDeletedVenue']);

// ...

$venueData = LocationFields::readMeta($postId);
$venueData['venue_name'] = get_the_title($postId);

foreach ($referencingEvents as $eventId) {
    // copy the venue's current details onto the event's own fields
    // ...
    delete_post_meta($eventId, '_scem_venue_id');
}

Every event that referenced the venue gets its current details written into that event’s own manual location fields, and then the reference is cleared. The event keeps exactly the address it had a second earlier. It simply stops being linked to something that no longer exists, and falls back to the same manual fields it would have used if the venue had never been saved as a venue in the first place.

Two details worth noting. It’s before_delete_post, not the trash hook — trashing a venue is reversible and leaves the link intact, which is right, because restoring it should restore the relationship too. And the events stop updating from that point, which is also right: there’s nothing left to update from, and a frozen correct address beats a live broken one.

The mechanism only exists because the plugin had already committed to references over copies. If events had stored their own copy of the address all along, none of this would be needed — and neither would the thing that makes references worth having.

Deleting a venue shouldn’t be able to damage an event that had nothing to do with the decision. Somebody clearing out an admin list is not consenting to break the public site.