PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/uberviewer/website/get_activity.php

http://gdata-samples.googlecode.com/
PHP | 407 lines | 313 code | 26 blank | 68 comment | 42 complexity | 3954b4b673a673cae177d04dbd12b0a4 MD5 | raw file
Possible License(s): Apache-2.0, MIT, LGPL-2.1
  1. <?php
  2. /* Copyright (c) 2009 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. * Author: Jochen Hartmann <api.jhartmann@google.com>
  17. */
  18. require_once 'config.inc.php';
  19. require_once 'Zend/Loader.php';
  20. Zend_Loader::loadClass('Zend_Gdata_YouTube');
  21. Zend_Loader::loadClass('Zend_Gdata_AuthSub');
  22. /*
  23. * Echo feed from either memcache or DB.
  24. * @param integer $page The page of results to display
  25. * @return void
  26. */
  27. function retrieveFeed($page = 1) {
  28. $memcache = getMemcache();
  29. $feed = null;
  30. if ($memcache !== null) {
  31. $feed = $memcache->get('the-ueber-feed_page-' . $page);
  32. }
  33. if ($feed && strlen($feed) > 10) {
  34. return $feed;
  35. } else {
  36. $dbFeedArray = getFeedFromDB($page);
  37. $metaDataFeedArray = addMetaData($dbFeedArray);
  38. unset($dbFeedArray);
  39. $jsonOutput = json_encode($metaDataFeedArray);
  40. $memcache = getMemcache();
  41. if ($memcache !== null) {
  42. $expirationTime = $GLOBALS['ueber-activity-viewer-php_config']['feed_expiry_time'] ;
  43. $key = 'the-ueber-feed_page-'. $page;
  44. $memcache->set($key, $jsonOutput, MEMCACHE_COMPRESSED, $expirationTime);
  45. }
  46. return $jsonOutput;
  47. }
  48. }
  49. /*
  50. * Returns a Memcache object to interact with the memcache servers
  51. * @return Resource|null Returns a reference to memcache if enabled/found or null
  52. */
  53. function getMemcache() {
  54. if($GLOBALS['ueber-activity-viewer-php_config']['enable_memcache']) {
  55. $memcache = new Memcache;
  56. $server = $GLOBALS['ueber-activity-viewer-php_config']['memcache_server'];
  57. $port = $GLOBALS['ueber-activity-viewer-php_config']['memcache_port'];
  58. if (@$memcache->connect($server, $port) !== FALSE) {
  59. return $memcache;
  60. }
  61. }
  62. return null;
  63. }
  64. /**
  65. * Return the entire feed of activities from the DB
  66. * @param integer $page The page of results to retrieve from the DB
  67. * @return array|null The feed of activities as array or null if error
  68. */
  69. function getFeedFromDB($page = 1) {
  70. $mysqli = new mysqli(
  71. $GLOBALS['ueber-activity-viewer-php_config']['mysql_hostname'],
  72. $GLOBALS['ueber-activity-viewer-php_config']['mysql_username'],
  73. $GLOBALS['ueber-activity-viewer-php_config']['mysql_password'],
  74. $GLOBALS['ueber-activity-viewer-php_config']['mysql_database'],
  75. $GLOBALS['ueber-activity-viewer-php_config']['mysql_port'],
  76. $GLOBALS['ueber-activity-viewer-php_config']['mysql_socket']);
  77. if (mysqli_connect_errno()) {
  78. error_log("Connect failed: " . mysqli_connect_error());
  79. return null;
  80. }
  81. $output = array();
  82. $numItemsPerPage = $GLOBALS['ueber-activity-viewer-php_config']['num_items_to_page'];
  83. if (intval($page) == 0) {
  84. $page = 1;
  85. }
  86. if ($page > 1) {
  87. $statement = $mysqli->prepare(
  88. "SELECT username, updated, json FROM activity ORDER BY updated DESC LIMIT ? OFFSET ?");
  89. $offset = $numItemsPerPage*($page);
  90. $statement->bind_param('ii', $numItemsPerPage, $offset);
  91. } else {
  92. $statement = $mysqli->prepare(
  93. "SELECT username, updated, json FROM activity ORDER BY updated DESC LIMIT ?");
  94. $statement->bind_param('i', $numItemsPerPage);
  95. }
  96. $statement->execute();
  97. $statement->store_result();
  98. $returnValue = null;
  99. if ($statement->num_rows < 1) {
  100. error_log("No rows returned: " . $statement->num_rows);
  101. } else {
  102. $statement->bind_result($username, $updated, $json);
  103. while ($statement->fetch()) {
  104. $output[] = array('author' => $username, 'updated' => $updated, 'json' => $json);
  105. }
  106. $returnValue = $output;
  107. }
  108. $statement->close();
  109. $mysqli->close();
  110. return $returnValue;
  111. }
  112. /**
  113. * Add metadata from the YouTube API or memcache for activity entries.
  114. * @param array $feedArray An array of activity entries for which we need metadata
  115. * @return array The new feed which contains metadata.
  116. */
  117. function addMetaData($feedArray) {
  118. $output = array();
  119. foreach($feedArray as $activityStream) {
  120. $author = $activityStream['author'];
  121. $updated = $activityStream['updated'];
  122. $event = json_decode($activityStream['json'], TRUE);
  123. if (strpos($event['event'], 'VIDEO') !== FALSE) {
  124. $event['metadata'] = getVideoMetadata($event['videoid']);
  125. } else {
  126. $event['metadata'] = getUserProfileMetadata($event['username']);
  127. }
  128. $output[] = array('author' => $author, 'updated' => $updated,
  129. 'event' => $event);
  130. }
  131. return $output;
  132. }
  133. /**
  134. * Add metadata from the YouTube API or memcache for a user profile.
  135. * @param string $username The username for which to fetch metadata
  136. * @return array|null An associated array of metadata, if found.
  137. */
  138. function getUserProfileMetadata($username) {
  139. // look in memcache first
  140. $memcache = getMemcache();
  141. if ($memcache) {
  142. $outputArray = $memcache->get('username-' . $username);
  143. if ($outputArray) {
  144. return $outputArray;
  145. }
  146. }
  147. $yt = getYouTubeService();
  148. $userProfile = null;
  149. try {
  150. $userProfile = $yt->getUserProfile($username);
  151. } catch(Exception $e) {
  152. error_log("Could not get user profile from YT API: " .
  153. $e->getMessage());
  154. return null;
  155. }
  156. $profileData = array();
  157. $profileData['about_me'] = $userProfile->getAboutMe()->text;
  158. $profileData['first_name'] = $userProfile->getFirstName()->text;
  159. $profileData['last_name'] = $userProfile->getLastName()->text;
  160. $thumbnail = $userProfile->getThumbnail();
  161. if ($thumbnail) {
  162. $profileData['thumbnail_url'] = $thumbnail->getUrl();
  163. }
  164. $profileData['age'] = $userProfile->getAge()->text;
  165. $profileData['books'] = $userProfile->getBooks()->text;
  166. $profileData['company'] = $userProfile->getCompany()->text;
  167. $profileData['hobbies'] = $userProfile->getHobbies()->text;
  168. $profileData['hometown'] = $userProfile->getHometown()->text;
  169. $profileData['location'] = $userProfile->getLocation()->text;
  170. $profileData['movies'] = $userProfile->getMovies()->text;
  171. $relLink = $userProfile->getLink('related');
  172. if ($relLink) {
  173. $profileData['website_url'] = $relLink->getHref();
  174. }
  175. $profileData['gender'] = $userProfile->getGender()->text;
  176. $profileData['relationship'] = $userProfile->getRelationship()->text;
  177. $profileData['music'] = $userProfile->getMusic()->text;
  178. $profileData['occupation'] = $userProfile->getOccupation()->text;
  179. $profileData['school'] = $userProfile->getSchool()->text;
  180. $profileData['member_since'] = $userProfile->getPublished()->text;
  181. $profileData['last_profile_update'] = $userProfile->getUpdated()->text;
  182. $profileData['num_favorites'] = $userProfile->getFeedLink(
  183. 'http://gdata.youtube.com/schemas/2007#user.favorites')->countHint;
  184. $profileData['num_contacts'] = $userProfile->getFeedLink(
  185. 'http://gdata.youtube.com/schemas/2007#user.contacts')->countHint;
  186. $profileData['num_subscriptions'] = $userProfile->getFeedLink(
  187. 'http://gdata.youtube.com/schemas/2007#user.subscriptions')->countHint;
  188. $profileData['num_uploads'] = $userProfile->getFeedLink(
  189. 'http://gdata.youtube.com/schemas/2007#user.uploads')->countHint;
  190. $statistics = $userProfile->getStatistics();
  191. $profileData['channel_views'] = $statistics->getViewCount();
  192. $profileData['videos_watched'] = $statistics->getVideoWatchCount();
  193. $profileData['subscribers'] = $statistics->getSubscriberCount();
  194. $profileData['last_login'] = $statistics->getLastWebAccess();
  195. $outputArray = array();
  196. // remove items that are null
  197. foreach($profileData as $key=>$value) {
  198. if ($value) {
  199. $outputArray[$key] = $value;
  200. }
  201. }
  202. $memcache = getMemcache();
  203. if ($memcache) {
  204. $key = 'username-' . $username;
  205. $metadata_expiration = $GLOBALS['ueber-activity-viewer-php_config']['metadata_expiry_time'];
  206. $memcache->set($key, $outputArray, MEMCACHE_COMPRESSED, $metadata_expiration);
  207. }
  208. return $outputArray;
  209. }
  210. /**
  211. * Get video metadata from the YouTube API or memcache
  212. * @param string $videoId The ID of the video for which to get metadata
  213. * @return array An associated array of metadata
  214. */
  215. function getVideoMetadata($videoId) {
  216. // look in memcache first
  217. $memcache = getMemcache();
  218. if ($memcache) {
  219. $outputArray = $memcache->get('video-' . $videoId);
  220. if ($outputArray) {
  221. return $outputArray;
  222. }
  223. }
  224. $yt = getYouTubeService();
  225. $videoEntry = null;
  226. try {
  227. $videoEntry = $yt->getVideoEntry(null,
  228. 'http://gdata.youtube.com/feeds/api/videos/' .
  229. $videoId);
  230. } catch (Exception $e) {
  231. error_log("Could not get video from YT API: " .
  232. $e->getMessage());
  233. return null;
  234. }
  235. $videoData = array();
  236. $videoData['video_title'] = $videoEntry->getVideoTitle();
  237. $videoData['watch_page_url'] = $videoEntry->getVideoWatchPageUrl();
  238. $videoData['swf_url'] = $videoEntry->getFlashPlayerUrl();
  239. $videoData['duration'] = $videoEntry->getVideoDuration();
  240. $videoData['view_count'] = $videoEntry->getVideoViewCount();
  241. $videoData['video_recorded'] = $videoEntry->getVideoRecorded();
  242. $videoData['video_description'] = $videoEntry->getVideoDescription();
  243. $tags = $videoEntry->getVideoTags();
  244. if ($tags) {
  245. if (count($tags) > 5) {
  246. $tags = array_slice($tags, 0, 5);
  247. }
  248. $videoData['video_tags'] = 'Tags: ' . implode(' ', $tags);
  249. }
  250. $geoLoc = $videoEntry->getVideoGeoLocation();
  251. if ($geoLoc) {
  252. $videoData['geo_location'] = 'Geo location: ' . implode(', ', $geoLoc);
  253. }
  254. $rating = $videoEntry->getVideoRatingInfo();
  255. if ($rating) {
  256. $ratingString = 'Ratings so far: ';
  257. foreach($rating as $key=>$value) {
  258. $ratingString .= strtoupper(substr($key, 0, 1)) . substr($key, 1) . " : " . $value . " | ";
  259. }
  260. $videoData['video_rating'] = trim($ratingString);
  261. }
  262. $videoData['video_category'] = 'Category: ' . $videoEntry->getVideoCategory();
  263. $videoThumbnails = $videoEntry->getVideoThumbnails();
  264. if (count($videoThumbnails)) {
  265. $videoData['thumb_url'] = $videoThumbnails[0]['url'];
  266. }
  267. $outputArray = array();
  268. // strip out items that are null
  269. foreach($videoData as $key=>$value) {
  270. if ($value) {
  271. $outputArray[$key] = $value;
  272. }
  273. }
  274. $memcache = getMemcache();
  275. if ($memcache) {
  276. $key = 'video-' . $videoId;
  277. $metadata_expiration = $GLOBALS['ueber-activity-viewer-php_config']['metadata_expiry_time'];
  278. $memcache->set($key, $outputArray, MEMCACHE_COMPRESSED, $metadata_expiration);
  279. }
  280. return $outputArray;
  281. }
  282. /**
  283. * Get the URL for the AuthSub login page.
  284. *
  285. * @return string The URL
  286. */
  287. function createLoginUrl() {
  288. $next = "http://{$_SERVER['SERVER_NAME']}{$_SERVER['PHP_SELF']}";
  289. $scope = 'http://gdata.youtube.com';
  290. $secure = false;
  291. $session = true;
  292. return Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, $session);
  293. }
  294. /**
  295. * Add a username to the DB using their single-use AuthSub token.
  296. *
  297. * @param string $token The single-use AuthSub token of the user to be added.
  298. * @return void
  299. */
  300. function addUsername($token) {
  301. $httpClient = Zend_Gdata_AuthSub::getHttpClient($token);
  302. $yt = new Zend_Gdata_YouTube($httpClient, 'YT-UeberActivityViewer',
  303. $GLOBALS['ueber-activity-viewer-php_config']['client_id'],
  304. $GLOBALS['ueber-activity-viewer-php_config']['dev_key']);
  305. $yt->setMajorProtocolVersion(2);
  306. try {
  307. $userProfile = $yt->getUserProfile('default');
  308. } catch (Zend_Gdata_Exception $e) {
  309. error_log("Error getting userProfile: " . $e->getMessage());
  310. return null;
  311. }
  312. unset($yt);
  313. if (!$userProfile) {
  314. error_log("UserProfile is null.");
  315. return null;
  316. }
  317. $username = $userProfile->getUsername();
  318. $userhash = null;
  319. // get hash
  320. if ($username) {
  321. $yt = getYouTubeService();
  322. try {
  323. $activitiesFeed = $yt->getFeed('http://gdata.youtube.com/feeds/api/users/' .
  324. $username . '/events');
  325. } catch (Exception $e) {
  326. echo "Error retrieving user events feed for $username | " . $e->getMessage();
  327. print_r($yt);
  328. }
  329. $updatesLink = $activitiesFeed->getLink('updates');
  330. $hashHref = $updatesLink->getHref();
  331. $userhash = substr($hashHref, (strpos($hashHref, '#')+1));
  332. unset($yt);
  333. } else {
  334. echo "Could not get user profile for token $token.";
  335. error_log("Could not get user profile for token $token.");
  336. header('Location: ' . "http://{$_SERVER['SERVER_NAME']}{$_SERVER['PHP_SELF']}");
  337. }
  338. $mysqli = new mysqli(
  339. $GLOBALS['ueber-activity-viewer-php_config']['mysql_hostname'],
  340. $GLOBALS['ueber-activity-viewer-php_config']['mysql_username'],
  341. $GLOBALS['ueber-activity-viewer-php_config']['mysql_password'],
  342. $GLOBALS['ueber-activity-viewer-php_config']['mysql_database'],
  343. $GLOBALS['ueber-activity-viewer-php_config']['mysql_port'],
  344. $GLOBALS['ueber-activity-viewer-php_config']['mysql_socket']);
  345. if (mysqli_connect_errno()) {
  346. error_log("Connect failed: " . mysqli_connect_error());
  347. return null;
  348. }
  349. $username = $mysqli->real_escape_string($username);
  350. $userhash = $mysqli->real_escape_string($userhash);
  351. $statement = $mysqli->prepare(
  352. "INSERT IGNORE INTO user (username, hash) VALUES (?,?)");
  353. $statement->bind_param('ss', $username, $userhash);
  354. $statement->execute();
  355. $statement->close();
  356. $mysqli->close();
  357. header('Location: ' . "http://{$_SERVER['SERVER_NAME']}{$_SERVER['PHP_SELF']}");
  358. }
  359. /**
  360. * Return a new instance of a v2 YouTube service object
  361. * @return Zend_Gdata_YouTube YouTube service object
  362. */
  363. function getYouTubeService() {
  364. $yt = new Zend_Gdata_YouTube(null, 'YT-UeberActivityViewer',
  365. $GLOBALS['ueber-activity-viewer-php_config']['client_id'],
  366. $GLOBALS['ueber-activity-viewer-php_config']['dev_key']);
  367. $yt->setMajorProtocolVersion(2);
  368. return $yt;
  369. }
  370. /**
  371. * The main loop for the application
  372. */
  373. function handleRequest() {
  374. if (isset($_GET['token'])) {
  375. addUsername($_GET['token']);
  376. } else if (isset($_GET['action'])) {
  377. echo retrieveFeed($_GET['page']);
  378. }
  379. }
  380. handleRequest();
  381. ?>