Preventing our email system from triggering reservation deletions

When we re-did our DLINQ site, I set up a custom reservation system mixing Events Calendar Pro and Gravity Forms. One piece was sending out confirmation emails that include a URL that would enable people who registered to cancel their reservations. It was just a URL in the email with a URL parameter that acts as a code to confirm reservation deletion. So it’d look something like this.

https://multisitetwo.local/event/strange-tools-creative-applications-of-ai/?delete=jBkR9RK6wKBdMxSkY0RW

A number of our reservations were being canceled but people indicated they weren’t doing it. It appears that our email filtering/security service was scanning email URLs for security and that was resulting in the URLs being visited . . . and the reservations being canceled. I did not anticipate this.

So what I needed to was do two things. I changed the function from deleting the Gravity Forms submission to just altering the field where we register attendance to “canceled.”1 You can see that PHP function change below. It’s using the Gravity Forms API pattern.

//new option is non-destructive and just sets a value of 'Canceled' for the right field by ID
GFAPI::update_entry_field($entry_id, 8,'Canceled');			
//old result was a removal of the entry entirely
GFAPI::delete_entry( $entry_id );

So now that we’re being a little more gentle with our reservation cancelation process, I also want to make sure a human is hitting this URL and doing something to confirm they want to cancel the reservation. To do that we’ll use a bit of javascript to set a new second URL parameter.

function deleteByHumanHand() {
  if (window.location) {
    const newUrl = new URL(window.location.href);//get the URL
    const params = new URLSearchParams(newUrl.search);
    let confirmed = false;//default confirmed to false just in case
    
    if (params.has('delete') && !params.has('confirmed')) {//if we've got delete in the URL but NO confirmed
      confirmed = confirm("Are you sure you want to delete your reservation?");//throw up a prompt 
    }
    
    if (confirmed) {//if a person clicks yes on the prompt . . . 
      params.set("confirmed", "yes");//set confirmed to = yes
      newUrl.search = params.toString();
      window.location.replace(newUrl);//set the new URL
      alert('Thank you for confirming the deletion.');//push a confirmation message - this may be unnecessary
    }
  }
}

As part of the larger PHP function that does the actual work, we’re now going to check for two URL parameters (confirmed and delete).

function dlinq_check_to_delete(){
	$gf_workshop_registration_id = get_field('workshop_registration_form', 'option');
	if( 'tribe_events' == get_post_type()){//is it an event?
		if(isset($_GET["delete"]) && isset($_GET["confirmed"])){ //does it have two URL parameters set - delete and confirmed?
			$passcode = $_GET["delete"];
			$humanOk = $_GET['confirmed'];
			$search_criteria = array(
			    'status'        => 'active',
			    'field_filters' => array(
			        'mode' => 'any',
			        array(
			            'key'   => '11',//field that contains our secret code
			            'value' => $passcode //find an entry with the right code value
			        )
			    )
			);
			$entry = GFAPI::get_entries($gf_workshop_registration_id, $search_criteria);
			if(sizeof($entry)>0 && $humanOk != NULL){
				$entry_id = $entry[0]['id'];
				GFAPI::update_entry_field($entry_id, 8,'Canceled');//update the form entry			

				echo "<div class='notification delete-alert'>You have removed your reservation. Thank you.</div>";//echo out a confirmation message
			}			
		}
	}
}


1 I kind of knew this was a bad idea when I did it but I was fighting not to be a digital hoarder. I even wrote in the original comments that this might be a bad move.