//////////////////////////////////////////////////////////////////////////////
// A Shortcut guide to getting data from a Google Health EMR //
//////////////////////////////////////////////////////////////////////////////
// FIRST, go to www.google.com/h9, the Google Health developers' sandbox, and create yourself a free account. Put some dummy data in it, make up some medical conditions and tests.
// SECOND, download and install the Zend OAuth code from http://framework.zend.com/download/gdata
// THIRD, Change this to point to the location of your private signing key. What's a private signing key? See: http://code.google.com/apis/health/getting_started.html#DomainRegistration
define('HEALTH_PRIVATE_KEY', '/path/to/your/rsa_private_key.pem');
// The following AuthOpen authentication connects your application to Google.
// The legalities:
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Gdata
* @subpackage Demos
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
$EMRname = "Google Health";
//////////////////////////////////////////////////////////////////////////////
// End Configuration //
//////////////////////////////////////////////////////////////////////////////
// Load the Zend Gdata classes.
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_Health');
Zend_Loader::loadClass('Zend_Gdata_Health_Query');
session_start();
// Google H9 Sandbox AuthSub/OAuth scope
define('SCOPE', 'https://www.google.com/h9/feeds/');
try {
// Setup the HTTP client and fetch an AuthSub token for H9
$client = authenticate(@$_GET['token']);
$useH9 = true;
$healthService = new Zend_Gdata_Health($client, 'google-HealthPHPSample-v1.0', $useH9);
} catch(Zend_Gdata_App_Exception $e) {
$cmdData["loginMsg"]='Error: ' . $e->getMessage();
echo json_encode($cmdData);
exit;
}
//////////////////////////////////////////////////////////////////////////////
// End Authentication //
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Begin Sample Code //
//////////////////////////////////////////////////////////////////////////////
/*
if(isset($_GET["revoke"])) {
// =============================================================================
// Revoke the AuthSub session token
// =============================================================================
$revoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($client->getAuthSubToken(), $client) ? 'yes' : 'no';
unset($_SESSION['sessionToken']);
echo 'Link to EMR data revoked: ' . @$revoked;
exit;
}
*/
getTokenInfo($client); // this needed to make second and subsequent calls to this page work. Don't know exactly why.
//echo "Token info: ", getTokenInfo($client);
//echo "Session Token", $client->getAuthSubToken();
$query = new Zend_Gdata_Health_Query();
$query->setDigest("true");
$profileFeed = $healthService->getHealthProfileFeed($query);
// break down the feed
$entry = $profileFeed->entry[0]; // digest=true was set so we only have 1
$allergies = $entry->getCcr()->getAllergies();
$conditions = $entry->getCcr()->getConditions();
$immunizations = $entry->getCcr()->getImmunizations();
$tests = $entry->getCcr()->getLabResults();
$meds= $entry->getCcr()->getMedications();
$procedures = $entry->getCcr()->getProcedures();
// This is where your app starts. *************************************************
// You've got data, now parse it. For example:
getAllTests();
getAllMeds();
// An example of another way of using the medications data
//foreach ($meds as $med) {
//$xmlStr = $med->ownerDocument->saveXML($med);
//echo '' . $xmlStr . '
';
//}
//*********************************** supporting functions ***********************************
// get medical Test data from Google Health API
// To learn how to build these queries: http://code.google.com/apis/health/ccrg_reference.html
function getAllTests() {
global $tests;
$test = $tests->item(0);
$xpath = new DOMXpath($test->ownerDocument);
$testnames = $xpath->query("//ccr:Body/ccr:Results/ccr:Result/ccr:Test/ccr:Description/ccr:Text");
foreach ($testnames as $name) {
$nameOut[]= $name->nodeValue;
}
$dates= $xpath->query("//ccr:Body/ccr:Results/ccr:Result/ccr:Test/ccr:DateTime/ccr:ExactDateTime");
foreach ($dates as $date) {
$dateOut[] = $date->nodeValue; // human-readable
}
// continue with queries for other parts of the Tests.
}
// get data from Google Health API
function getAllMeds() {
global $meds;
// do your own thing
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// If you prefer to set queries by calling methods of a Query object, Google gives some sample code for that. //
// See http://framework.zend.com/svn/framework/standard/trunk/demos/Zend/Gdata/Health.php //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// more support functions *******************************************************
function getCurrentUrl() {
$phpRequestUri =
htmlentities(substr($_SERVER['REQUEST_URI'], 0, strcspn($_SERVER['REQUEST_URI'], "\n\r")), ENT_QUOTES);
if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
$protocol = 'https://';
} else {
$protocol = 'http://';
}
$host = $_SERVER['HTTP_HOST'];
if ($_SERVER['SERVER_PORT'] != '' &&
(($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') ||
($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) {
$port = ':' . $_SERVER['SERVER_PORT'];
} else {
$port = '';
}
return $protocol . $host . $port . $phpRequestUri;
}
function authenticate($singleUseToken=null) {
global $cmdData,$EMRname;
$sessionToken = isset($_SESSION['sessionToken']) ? $_SESSION['sessionToken'] : null;
// If there is no AuthSub session or one-time token waiting for us,
// redirect the user to Google Health's AuthSub handler to get one.
if (!$sessionToken && !$singleUseToken) {
$next = getCurrentUrl(); // 'next' is where you want to go after the user says it's ok to link to you.
$secure = 1;
$session = 1;
$authSubHandler = 'https://www.google.com/h9/authsub';
$permission = 1; // 1 - allows reading of the profile && posting notices
$authSubURL = Zend_Gdata_AuthSub::getAuthSubTokenUri($next, SCOPE, $secure, $session, $authSubHandler);
$authSubURL .= '&permission=' . $permission;
$cmdData["loginMsg"]="VisiHealth will graphically display your already-existing health account on $EMRname.
First step: Link your Google Health Account
";
echo json_encode($cmdData);
exit();
}
$client = new Zend_Gdata_HttpClient();
$client->setAuthSubPrivateKeyFile(HEALTH_PRIVATE_KEY, null, true);
// Convert an AuthSub one-time token into a session token if needed
if ($singleUseToken && !$sessionToken) {
//echo "session:$sessionToken ";
//echo "single:$singleUseToken ";
$sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken, $client);
$_SESSION['sessionToken'] = $sessionToken;
}
$client->setAuthSubToken($sessionToken);
return $client;
}
function getTokenInfo($client) {
$sessionToken = $client->getAuthSubToken();
return Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken, $client);
}
function revokeToken($client) {
$sessionToken = $client->getAuthSubToken();
return Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken, $client);
}
/** Prettifies an XML string into a human-readable and indented work of art
* @param string $xml The XML as a string
* @param boolean $html_output True if the output should be escaped (for use in HTML)
*/
function xmlpp($xml, $html_output=true) {
$xml_obj = new SimpleXMLElement($xml);
$level = 4;
$indent = 0; // current indentation level
$pretty = array();
// get an array containing each XML element
$xml = explode("\n", preg_replace('/>\s*', ">\n<", $xml_obj->asXML()));
// shift off opening XML tag if present
if (count($xml) && preg_match('/^<\?\s*xml/', $xml[0])) {
$pretty[] = array_shift($xml);
}
foreach ($xml as $el) {
if (preg_match('/^<([\w])+[^>\/]*>$/U', $el)) {
// opening tag, increase indent
$pretty[] = str_repeat(' ', $indent) . $el;
$indent += $level;
} else {
if (preg_match('/^<\/.+>$/', $el)) {
$indent -= $level; // closing tag, decrease indent
}
if ($indent < 0) {
$indent += $level;
}
$pretty[] = str_repeat(' ', $indent) . $el;
}
}
$xml = implode("\n", $pretty);
return ($html_output) ? htmlentities($xml) : $xml;
}