" . "\n"; $result .= "" . "\n"; $result .= "" . "\n"; $result .= "" . $_POST['recipe_title'] . "" . "\n"; $result .= "" . $_POST['cuisine'] . "" . "\n"; $result .= "Recipes" . "\n"; $result .= "" . $_POST['time_val'] . " " . $_POST['time_units'] . "" . "\n"; $result .= "" . $_POST['main_ingredient'] . "" . "\n"; $result .= "" . $_POST['serves'] . "" . "\n"; $result .= "" . $_POST['recipe_text'] . "" . "\n"; $result .= "" . "\n"; return $result; } /** * Creates the XML content used to perform a batch delete. */ function buildBatchXML() { $counter = 0; $result = '' . "\n"; $result .= ' $value) { if(substr($key, 0, 5) == "link_") { $counter++; $result .= '' . "\n"; $result .= '' . $value . '' . "\n"; $result .= '' . "\n"; $result .= '' . $counter . '' . "\n"; $result .= '' . "\n"; } } $result .= '' . "\n"; return $result; } /** * Exchanges the given single-use token for a session * token using AuthSubSessionToken, and returns the result. */ function exchangeToken($token) { $ch = curl_init(); /* Create a CURL handle. */ curl_setopt($ch, CURLOPT_URL, "https://www.google.com/accounts/AuthSubSessionToken"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FAILONERROR, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Authorization: AuthSub token="' . $token . '"' )); $result = curl_exec($ch); /* Execute the HTTP command. */ curl_close($ch); $splitStr = split("=", $result); return trim($splitStr[1]); } /** * Performs a query for all of the user's items using the * items feed, then parses the resulting XML with the * startElement, endElement and characterData functions * (below). */ function getItems($token) { $ch = curl_init(); /* Create a CURL handle. */ global $developerKey, $itemsFeedURL; curl_setopt($ch, CURLOPT_URL, $itemsFeedURL . "?"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/atom+xml', 'Authorization: AuthSub token="' . trim($token) . '"', 'X-Google-Key: key=' . $developerKey )); $result = curl_exec($ch); /* Execute the HTTP command. */ curl_close($ch); /* Parse the resulting XML. */ $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "startElement", "endElement"); xml_set_character_data_handler($xml_parser, "characterData"); xml_parse($xml_parser, $result); xml_parser_free($xml_parser); } /** * Inserts a new recipe by performing an HTTP POST to the * items feed. */ function postItem() { $ch = curl_init(); /* Create a CURL handle. */ global $developerKey, $itemsFeedURL; /* Set cURL options. */ curl_setopt($ch, CURLOPT_URL, $itemsFeedURL); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FAILONERROR, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Authorization: AuthSub token="' . $_POST['token'] . '"', 'X-Google-Key: key=' . $developerKey, 'Content-Type: application/atom+xml' )); curl_setopt($ch, CURLOPT_POSTFIELDS, buildInsertXML()); $result = curl_exec($ch); /* Execute the HTTP request. */ curl_close($ch); /* Close the cURL handle. */ return $result; } /** * Updates an existing recipe by performing an HTTP PUT * on its feed URI, using the updated values a PUT data. */ function updateItem() { $ch = curl_init(); /* Create a CURL handle. */ global $developerKey; /* Prepare the data for HTTP PUT. */ $putString = buildInsertXML(); $putData = tmpfile(); fwrite($putData, $putString); fseek($putData, 0); /* Set cURL options. */ curl_setopt($ch, CURLOPT_URL, $_POST['link']); curl_setopt($ch, CURLOPT_PUT, true); curl_setopt($ch, CURLOPT_INFILE, $putData); curl_setopt($ch, CURLOPT_INFILESIZE, strlen($putString)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FAILONERROR, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Authorization: AuthSub token="' . $_POST['token'] . '"', 'X-Google-Key: key=' . $developerKey, 'Content-Type: application/atom+xml' )); $result = curl_exec($ch); /* Execute the HTTP request. */ fclose($putData); /* Close and delete the temp file. */ curl_close($ch); /* Close the cURL handle. */ return $result; } /** * Deletes a recipe by performing an HTTP DELETE (a custom * cURL request) on its feed URI. */ function deleteItem() { $ch = curl_init(); global $developerKey; /* Set cURL options. */ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_setopt($ch, CURLOPT_URL, $_POST['link']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FAILONERROR, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Authorization: AuthSub token="' . $_POST['token'] . '"', 'X-Google-Key: key=' . $developerKey )); $result = curl_exec($ch); /* Execute the HTTP request. */ curl_close($ch); /* Close the cURL handle. */ return $result; } /** * Deletes all recipes by performing an HTTP POST to the * batch URI. */ function batchDelete() { $ch = curl_init(); /* Create a CURL handle. */ global $developerKey, $itemsFeedURL; /* Set cURL options. */ curl_setopt($ch, CURLOPT_URL, $itemsFeedURL . "/batch"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FAILONERROR, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Authorization: AuthSub token="' . $_POST['token'] . '"', 'X-Google-Key: key=' . $developerKey, 'Content-Type: application/atom+xml' )); curl_setopt($ch, CURLOPT_POSTFIELDS, buildBatchXML()); $result = curl_exec($ch); /* Execute the HTTP request. */ curl_close($ch); /* Close the cURL handle. */ return $result; } /** * Callback function for XML start tags parsed by * xml_parse. */ function startElement($parser, $name, $attrs) { global $curElement, $foundEntry, $parsedEntries; $curElement = $name; if($curElement == "ENTRY") { $foundEntry = true; $parsedEntries[count($parsedEntries)] = array(); } else if($foundEntry && $curElement == "LINK") { $parsedEntries[count($parsedEntries) - 1][$attrs["REL"]] = $attrs["HREF"]; } } /** * Callback function for XML end tags parsed by * xml_parse. */ function endElement($parser, $name) { global $curElement, $foundEntry, $parsedEntries; if($name == "ENTRY") { $foundEntry = false; } } /** * Callback function for XML character data parsed by * xml_parse. */ function characterData($parser, $data) { global $curElement, $foundEntry, $parsedEntries; if($foundEntry) { $parsedEntries[count($parsedEntries) - 1][strtolower($curElement)] = $data; } } /** * We arrive here when the user first comes to the form. The first step is * to have them get a single-use token. */ function showIntroPage() { global $itemsFeedURL; $next_url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; $redirect_url = 'https://www.google.com/accounts/AuthSubRequest?session=1'; $redirect_url .= '&next='; $redirect_url .= urlencode($next_url); $redirect_url .= "&scope="; $redirect_url .= urlencode($itemsFeedURL); print '' . "\n"; print 'PHP 4 Demo: Google Base data API' . "\n"; print '' . "\n"; print '' . "\n"; print '
' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '
PHP 4 Demo: Google Base data API
Before you get started, please sign in to your personal Google Base account.
' . "\n"; print '
' . "\n"; } /** * Prints the table of recipes the user has already entered * on the left-hand side of the page. */ function showRecipeListPane($token) { global $parsedEntries; print '' . "\n"; print '' . "\n"; print '' . "\n"; getItems($token); if(count($parsedEntries) == 0) { print '' . "\n"; } else { print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; for($i = 0; $i < count($parsedEntries); $i++) { print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; /* Create an Edit button for each existing recipe. */ print '' . "\n"; /* Create a Delete button for each existing recipe. */ print '' . "\n"; print '' . "\n"; } } /* Create a "Delete all" button" to demonstrate batch requests. */ print '' . "\n"; print '
Recipes you have added
(none)
NameCuisineServesActions
' . $parsedEntries[$i]['title'] . '' . $parsedEntries[$i]['g:cuisine'] . '' . $parsedEntries[$i]['g:serving_count'] . '' . "\n"; print '
' . "\n"; print '' . "\n"; print '' . "\n"; foreach ($parsedEntries[$i] as $key => $value) { print '' . "\n"; } print '' . "\n"; print '
' . "\n"; print '
' . "\n"; print '
' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '
' . "\n"; print '
' . "\n"; print '
' . "\n"; print '' . "\n"; print '' . "\n"; for($i = 0; $i < count($parsedEntries); $i++) { print '' . "\n"; } print '
' . "\n"; print '' . "\n"; } /** * Prints a small form allowing the user to insert a new * recipe. */ function showRecipeInsertPane($token) { global $cuisines; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '
Insert a new recipe
Title:' . '
Main ingredient:' . '
Cuisine:
Cooking Time: ' . '
Serves:
Recipe:
 
' . "\n"; print '' . "\n"; } /** * Shows a menu allowing the user to update an existing * recipe with the Base API update feature. */ function showEditMenu() { global $cuisines; $splitCookingTime = split(" ", $_POST['g:cooking_time']); print '' . "\n"; print 'PHP 4 Demo: Google Base data API' . "\n"; print '' . "\n"; print '' . "\n"; print '
' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '
Edit recipe:
Title:
Main ingredient:
Cuisine:
Cooking Time: ' . "\n"; print '
Serves:
Recipe:
 
' . "\n"; print '' . "\n"; } /** * Displays both the "List of current recipes" and * "Insert a new recipe" panels in a single table. */ function showMainMenu($tableTitle, $sessionToken) { print '' . "\n"; print 'PHP 4 Demo: Google Base data API' . "\n"; print '' . "\n"; print '' . "\n"; print '
' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; print '' . "\n"; // Create the two sub-tables. showRecipeListPane($sessionToken); showRecipeInsertPane($sessionToken); // Add a "Sign out" link. print '' . "\n"; // Close the master table. print '
PHP 4 Demo: Google Base data API' . "\n"; print '
' . $tableTitle . '
Or click here to' . ' sign out' . ' of your Google account.
' . "\n"; print '
' . "\n"; } /** * We arrive here after the user first authenticates and we get back * a single-use token. */ function showFirstAuthScreen() { $singleUseToken = $_GET['token']; $sessionToken = exchangeToken($singleUseToken); if(!$sessionToken) { showIntroPage(); } else { $tableTitle = 'Here\'s your single use token: ' . $singleUseToken . '' . "\n" . '
And here\'s the session token: ' . $sessionToken . ''; showMainMenu($tableTitle, $sessionToken); } } /** * Main logic. Take action based on the GET and POST * parameters, which reflect whether the user has * authenticated and which action they want to perform. */ if(count($_GET) == 1 && array_key_exists('token', $_GET)) { showFirstAuthScreen(); } else { if(count($_POST) == 0) { showIntroPage(); } else { if($_POST['action'] == 'insert') { if(postItem()) { showMainMenu('Recipe inserted!', $_POST['token']); } else { showMainMenu('Recipe insertion failed.', $_POST['token']); } } else if($_POST['action'] == 'delete') { if(deleteItem()) { showMainMenu('Recipe deleted.', $_POST['token']); } else { showMainMenu('Recipe deletion failed.', $_POST['token']); } } else if($_POST['action'] == 'delete_all') { if(batchDelete()) { showMainMenu('All recipes deleted.', $_POST['token']); } else { showMainMenu('Batch deletion failed.', $_POST['token']); } } else if($_POST['action'] == 'edit') { showEditMenu(); } else if($_POST['action'] == 'update') { if(updateItem()) { showMainMenu('Recipe successfully updated.', $_POST['token']); } else { showMainMenu('Recipe update failed.', $_POST['token']); } } else { showIntroPage(); } } } ?>