Bible Taxonomy – AJAX / WP Integration

BibleTax_Featured_5
Note: This post is series explaining how I created the new Bible Taxonomy tool as seen on DiscipleShare. To see it in action, or to find great, free curriculum to use in churches, visit: http://www.discipleshare.net/

So how does the user input get saved dynamically to the database? It already happens in a similar way with post tags. Users enter them on the fly and they’re processed and the user interface is updated without needing a postback or page refresh.

The hard part was figuring how to tap into the existing AJAX / PHP functions from my child theme. After some deep, deep digging, I found the interactions in the WordPress core.

The key: hook into your php function with ‘wp_ajax_’ appended to the javascript function’s name

add_action('wp_ajax_process_bible_verses', 'bible_verses_ADD_callback');
function bible_verses_ADD_callback() { 
	$verses = $_POST['verses'];
	$service = new IDWebService($verses);
	
	$verses = $service->verses;
	$xml = $service->xml;
	$id_firstBook = $service->id_firstBook;
	$id_firstChapter = $service->id_firstChapter;
	$id_firstVerse = $service->id_firstVerse;
	$id_secondBook = $service->id_secondBook;
	$id_secondChapter = $service->id_secondChapter;
	$id_secondVerse = $service->id_secondVerse;
	$id_sanitizedVerses = $service->sanitizedVerses;
	$exceptionBool = $service->exceptionBool;
	$exceptionMessage = $service->exceptionMessage;
	
	$verseformat  = $service->GetVerseFormat($verses);
	
	$service->__destruct(); // Did this to solve memory leak; http://paul-m-jones.com/archives/262
    unset($service); // however, leak probably came about from iterating through objects and not ints
	
	$post_id = intval( $_POST['post_id'] );
	
	try {		
		if ($exceptionBool == true) {
			//_log('exception prior to checking ...'.$exceptionMessage);
			die('<Error msg="'.$exceptionMessage.'" />');
		} else {
			switch ($verseformat) {
				case "B":
					$bibleIDs = array();
					$bibleIDs[] = $id_firstBook;
					$newCollectionID = bible_verses_addCollection($id_sanitizedVerses, $bibleIDs, $post_id);
					die('<collection id="'.$newCollectionID.'" name="'.$id_sanitizedVerses.'" />');
					break;
				case "B C":
					$bibleIDs = array();
					$bibleIDs[] = $id_firstBook;
					$bibleIDs[] = $id_firstChapter;
					$newCollectionID = bible_verses_addCollection($id_sanitizedVerses, $bibleIDs, $post_id);
					die('<collection id="'.$newCollectionID.'" name="'.$id_sanitizedVerses.'" />');
					break;
				case "B C:V":
					$bibleIDs = array();
					$bibleIDs[] = $id_firstBook;
					$bibleIDs[] = $id_firstChapter;
					$bibleIDs[] = $id_firstVerse;
					$newCollectionID = bible_verses_addCollection($id_sanitizedVerses, $bibleIDs, $post_id);
					die('<collection id="'.$newCollectionID.'" name="'.$id_sanitizedVerses.'" />');
					break;
				case "B C-C":
					$bibleIDs = array();
					$bibleIDs[] = $id_firstBook;
					$bibleIDs[] = $id_firstChapter;
					$bibleIDs[] = $id_secondChapter;
					// NOTE: Need to improve the logic to make this "B C-C" rather than "B C,C"
					$newCollectionID = bible_verses_addCollection($id_sanitizedVerses, $bibleIDs, $post_id);
					die('<collection id="'.$newCollectionID.'" name="'.$id_sanitizedVerses.'" />');
					break;
				case "B C:V-V":
					// check to make sure second verse > first verse
					if ($id_firstVerse >= $id_secondVerse) {
						die('<Error msg="Choose a starting verse before the ending verse">');
					}
					
					// _log('id_firstverse = '.$id_firstVerse);
					// _log('id_secondverse = '.$id_secondVerse);
					
					$bibleIDs = array();
					$bibleIDs[] = $id_firstBook;
					$bibleIDs[] = $id_firstChapter;
					for ($i = $id_firstVerse*1; $i < $id_secondVerse*1+1; $i++) {
						$bibleIDs[] = $i;
					}
					$newCollectionID = bible_verses_addCollection($id_sanitizedVerses, $bibleIDs, $post_id);
					die('<collection id="'.$newCollectionID.'" name="'.$id_sanitizedVerses.'" />');
					break;
				case "B C:V,V":
					$bibleIDs = array();
					$bibleIDs[] = $id_firstBook;
					$bibleIDs[] = $id_firstChapter;
					$bibleIDs[] = $id_firstVerse;
					$bibleIDs[] = $id_secondVerse;
					$newCollectionID = bible_verses_addCollection($id_sanitizedVerses, $bibleIDs, $post_id);
					die('<collection id="'.$newCollectionID.'" name="'.$id_sanitizedVerses.'" />');
					break;
				case "B C:V - C:V":
				case "B C:V - B C:V":
					// check to make sure second verse > first verse
					if ((int)$id_firstVerse >= (int)$id_secondVerse) {
						die('<Error msg="Choose a starting verse before the ending verse">');
					}

					$bibleIDs = array();
					$bibleIDs[] = $id_firstBook;
					$bibleIDs[] = $id_firstChapter;
					for ($i = $id_firstVerse*1; $i < $id_secondVerse*1+1; $i++) {
						$bibleIDs[] = $i;
					}
					$newCollectionID = bible_verses_addCollection($id_sanitizedVerses, $bibleIDs, $post_id);
					die('<collection id="'.$newCollectionID.'" name="'.$id_sanitizedVerses.'" />');
					break;
				case "Error: Unknown Format (Book should be followed by Chapter number)":
				case "Error: Unknown Format (Are you missing a chapter?)":
				case "Error: Unknown Format (Are you trying to reference more than one verse?  We suggest Book Chapter:Verse - Verse format)":
					echo '<Error ';
					echo 'msg="'.$verseformat.'" />';
					break;
				default:
					echo ',';
					echo '<Error msg="Error: unknown Format" />';
			}
		}
		
		// IMPORTANT: don't forget to "exit"
		exit;

	} catch (Exception $e) {
		die('<Error msg="'.$e.'" />');
		exit;
	}
}

Once the interaction’s happening correctly, the database insert statements look like normal SQL statements in the PHP:


function bible_verses_addCollection($collectionName, $arrayIds, $post_id) {
	global $wpdb;
	
	// Add collection to table
	$rowstatus = $wpdb->insert( $wpdb->prefix . "bible_terms_taxonomy", array( 'taxonomy' => $collectionName, 'term_id' => $post_id) );
	$collectionID = $wpdb->insert_id;
	
	if ($rowstatus == 1) {
		foreach($arrayIds as $elemID) {
			$relationshipRowStatus = $wpdb->insert( $wpdb->prefix . "bible_terms_relationships", array('object_id' => $collectionID, 'term_id' => $elemID));
			if ($relationshipRowStatus == 0) {
				$rowstatus = 0;
			}
		}
		return $collectionID;
	} else {
		return -1;
	}
}

I ended up creating similar AJAX methods for the delete and GET / SELECT so that the Javascript methods had easy PHP functions to call.

Comments

  1. So this is added to the function.php of a child theme? I’m recently learning to program by necessity. Looks like exactly what I’m trying to do, have sermons posted and referenced by verse.

  2. Adam Frieberg says:

    Function.php is the place, Phil. Good luck – and let me know if you need help getting it working.

Speak Your Mind