summaryrefslogtreecommitdiff
path: root/zend/demos/Zend/Gdata/YouTubeVideoApp
diff options
context:
space:
mode:
Diffstat (limited to 'zend/demos/Zend/Gdata/YouTubeVideoApp')
-rw-r--r--zend/demos/Zend/Gdata/YouTubeVideoApp/README.txt44
-rwxr-xr-xzend/demos/Zend/Gdata/YouTubeVideoApp/index.php193
-rwxr-xr-xzend/demos/Zend/Gdata/YouTubeVideoApp/notfound.jpgbin0 -> 1345 bytes
-rwxr-xr-xzend/demos/Zend/Gdata/YouTubeVideoApp/operations.php1097
-rwxr-xr-xzend/demos/Zend/Gdata/YouTubeVideoApp/session_details.php66
-rwxr-xr-xzend/demos/Zend/Gdata/YouTubeVideoApp/video_app.css236
-rwxr-xr-xzend/demos/Zend/Gdata/YouTubeVideoApp/video_app.js582
7 files changed, 2218 insertions, 0 deletions
diff --git a/zend/demos/Zend/Gdata/YouTubeVideoApp/README.txt b/zend/demos/Zend/Gdata/YouTubeVideoApp/README.txt
new file mode 100644
index 0000000..3cea242
--- /dev/null
+++ b/zend/demos/Zend/Gdata/YouTubeVideoApp/README.txt
@@ -0,0 +1,44 @@
+== YouTube data API Video App in PHP ==
+
+PHP sample code for the YouTube data API. Utilizes the Zend Framework
+Zend_Gdata component to communicate with the YouTube data API.
+
+Requires the Zend Framework Zend_Gdata component and PHP >= 5.2.11
+This sample is run from within a web browser. These files are required:
+
+session_details.php - a script to view log output and session variables
+operations.php - the main logic, which interfaces with the YouTube API
+index.php - the HTML to represent the web UI, contains some PHP
+video_app.css - the CSS to define the interface style
+video_app.js - the JavaScript used to provide the video list AJAX interface
+
+--------------
+
+NOTE: If using in production, some additional precautions with regards
+to filtering the input data should be used. This code is designed only
+for demonstration purposes.
+
+--------------
+
+Please be sure to obtain a Developer Key from YouTube prior to using
+this application by visiting this site:
+
+http://code.google.com/apis/youtube/dashboard/
+
+More information on the YouTube Data API and Tools is available here:
+
+http://code.google.com/apis/youtube
+
+For a video explaining the basics of how this application works, please
+visit this link:
+
+http://www.youtube.com/watch?v=iIp7OnHXBlo
+
+To see this application running live, please visit:
+
+http://googlecodesamples.com
+
+== UPDATES ==
+
+3/2009 - Removed functionality to set the Developer Key in a form. Instead,
+ it is now hard-coded in the index.php page. This reduces complexity.
diff --git a/zend/demos/Zend/Gdata/YouTubeVideoApp/index.php b/zend/demos/Zend/Gdata/YouTubeVideoApp/index.php
new file mode 100755
index 0000000..45cee26
--- /dev/null
+++ b/zend/demos/Zend/Gdata/YouTubeVideoApp/index.php
@@ -0,0 +1,193 @@
+<?php
+/**
+ * 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
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * PHP sample code for the YouTube data API. Utilizes the Zend Framework
+ * Zend_Gdata component to communicate with the YouTube data API.
+ *
+ * Requires the Zend Framework Zend_Gdata component and PHP >= 5.2.11
+ * This sample is run from within a web browser. These files are required:
+ * session_details.php - a script to view log output and session variables
+ * operations.php - the main logic, which interfaces with the YouTube API
+ * index.php - the HTML to represent the web UI, contains some PHP
+ * video_app.css - the CSS to define the interface style
+ * video_app.js - the JavaScript used to provide the video list AJAX interface
+ *
+ * NOTE: If using in production, some additional precautions with regards
+ * to filtering the input data should be used. This code is designed only
+ * for demonstration purposes.
+ */
+session_start();
+
+/**
+ * Set your developer key here.
+ *
+ * NOTE: In a production application you may want to store this information in
+ * an external file.
+ */
+$_SESSION['developerKey'] = '<YOUR DEVELOPER KEY>';
+
+/**
+ * Convert HTTP status into normal text.
+ *
+ * @param number $status HTTP status received after posting syndicated upload
+ * @param string $code Alphanumeric description of error
+ * @param string $videoId (optional) Video id received back to which the status
+ * code refers to
+ */
+function uploadStatus($status, $code = null, $videoId = null)
+{
+ switch ($status) {
+ case $status < 400:
+ echo 'Success ! Entry created (id: '. $videoId .
+ ') <a href="#" onclick=" ytVideoApp.checkUploadDetails(\''.
+ $videoId .'\'); ">(check details)</a>';
+ break;
+ default:
+ echo 'There seems to have been an error: '. $code .
+ '<a href="#" onclick=" ytVideoApp.checkUploadDetails(\''.
+ $videoId . '\'); ">(check details)</a>';
+ }
+}
+
+/**
+ * Helper function to check whether a session token has been set
+ *
+ * @return boolean Returns true if a session token has been set
+ */
+function authenticated()
+{
+ if (isset($_SESSION['sessionToken'])) {
+ return true;
+ }
+}
+
+/**
+ * Helper function to print a list of authenticated actions for a user.
+ */
+function printAuthenticatedActions()
+{
+ print <<<END
+ <div id="actions"><h3>Authenticated Actions</h3>
+ <ul>
+ <li><a href="#" onclick="ytVideoApp.listVideos('search_owner', '', 1);
+ return false;">retrieve my videos</a></li>
+ <li><a href="#" onclick="ytVideoApp.prepareUploadForm();
+ return false;">upload a video</a><br />
+ <div id="syndicatedUploadDiv"></div><div id="syndicatedUploadStatusDiv">
+ </div></li>
+ <li><a href="#" onclick="ytVideoApp.retrievePlaylists();
+ return false;">manage my playlists</a><br /></li>
+ </ul></div>
+END;
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <title>YouTube data API Video Browser in PHP</title>
+ <link href="video_app.css" type="text/css" rel="stylesheet" />
+ <script src="video_app.js" type="text/javascript"></script>
+</head>
+
+<body>
+ <div id="main">
+ <div id="titleBar">
+ <h2>YouTube data API Video App in PHP</h2>
+ <a href="session_details.php">click to examine session variables</a><br/>
+ <div id="searchBox">
+ <form id="searchForm" onsubmit="ytVideoApp.listVideos(this.queryType.value, this.searchTerm.value, 1); return false;" action="javascript:void();" >
+ <div id="searchBoxTop"><select name="queryType" onchange="ytVideoApp.queryTypeChanged(this.value, this.form.searchTerm);" >
+ <option value="search_all" selected="selected">All Videos</option>
+ <option value="search_top_rated">Top Rated Videos</option>
+ <option value="search_most_viewed">Most Viewed Videos</option>
+ <option value="search_recently_featured">Recently Featured Videos</option>
+ <option value="search_username">Videos from a specific user</option>
+ <?php
+ if (authenticated()) {
+ echo '<option value="search_owner">Display my videos</option>';
+ }
+ ?>
+ </select></div>
+ <div><input name="searchTerm" type="text" value="YouTube Data API" />
+ <input type="submit" value="Search" /></div>
+ </form>
+ </div>
+ <br />
+
+ </div>
+ <br />
+ <!-- Authentication status -->
+ <div id="authStatus">Authentication status:
+ <?php
+ if (authenticated()) {
+ print <<<END
+ authenticated <br />
+END;
+ } else {
+ print <<<END
+ <div id="generateAuthSubLink"><a href="#"
+ onclick="ytVideoApp.presentAuthLink();
+ return false;">Click here to generate authentication link</a>
+ </div>
+END;
+ }
+ ?>
+ </div>
+ <!-- end Authentication status -->
+ <br clear="all" />
+ <?php
+ // if $_GET['status'] is populated then we have a response
+ // about a syndicated upload from YouTube's servers
+ if (isset($_GET['status'])) {
+ (isset($_GET['code']) ? $code = $_GET['code'] : $code = null);
+ (isset($_GET['id']) ? $id = $_GET['id'] : $id = null);
+ print '<div id="generalStatus">' .
+ uploadStatus($_GET['status'], $code, $id) .
+ '<div id="detailedUploadStatus"></div></div>';
+ }
+ ?>
+ <!-- General status -->
+ <?php
+ if (authenticated()) {
+ printAuthenticatedActions();
+ }
+ ?>
+ <!-- end General status -->
+ <br clear="all" />
+ <div id="searchResults">
+ <div id="searchResultsListColumn">
+ <div id="searchResultsVideoList"></div>
+ <div id="searchResultsNavigation">
+ <form id="navigationForm" action="javascript:void();">
+ <input type="button" id="previousPageButton" onclick="ytVideoApp.listVideos(ytVideoApp.previousQueryType, ytVideoApp.previousSearchTerm, ytVideoApp.previousPage);" value="Back" style="display: none;" />
+ <input type="button" id="nextPageButton" onclick="ytVideoApp.listVideos(ytVideoApp.previousQueryType, ytVideoApp.previousSearchTerm, ytVideoApp.nextPage);" value="Next" style="display: none;" />
+ </form>
+ </div>
+ </div>
+ <div id="searchResultsVideoColumn">
+ <div id="videoPlayer"></div>
+ </div>
+ </div>
+</div>
+</body>
+</html>
diff --git a/zend/demos/Zend/Gdata/YouTubeVideoApp/notfound.jpg b/zend/demos/Zend/Gdata/YouTubeVideoApp/notfound.jpg
new file mode 100755
index 0000000..76ec81c
--- /dev/null
+++ b/zend/demos/Zend/Gdata/YouTubeVideoApp/notfound.jpg
Binary files differ
diff --git a/zend/demos/Zend/Gdata/YouTubeVideoApp/operations.php b/zend/demos/Zend/Gdata/YouTubeVideoApp/operations.php
new file mode 100755
index 0000000..c149583
--- /dev/null
+++ b/zend/demos/Zend/Gdata/YouTubeVideoApp/operations.php
@@ -0,0 +1,1097 @@
+<?php
+/**
+ * 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
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * PHP sample code for the YouTube data API. Utilizes the Zend Framework
+ * Zend_Gdata component to communicate with the YouTube data API.
+ *
+ * Requires the Zend Framework Zend_Gdata component and PHP >= 5.2.11
+ * This sample is run from within a web browser. These files are required:
+ * session_details.php - a script to view log output and session variables
+ * operations.php - the main logic, which interfaces with the YouTube API
+ * index.php - the HTML to represent the web UI, contains some PHP
+ * video_app.css - the CSS to define the interface style
+ * video_app.js - the JavaScript used to provide the video list AJAX interface
+ *
+ * NOTE: If using in production, some additional precautions with regards
+ * to filtering the input data should be used. This code is designed only
+ * for demonstration purposes.
+ */
+require_once 'Zend/Loader.php';
+Zend_Loader::loadClass('Zend_Gdata_YouTube');
+Zend_Loader::loadClass('Zend_Gdata_AuthSub');
+Zend_Loader::loadClass('Zend_Gdata_App_Exception');
+
+/*
+ * The main controller logic.
+ *
+ * POST used for all authenticated requests
+ * otherwise use GET for retrieve and supplementary values
+ */
+session_start();
+setLogging('on');
+generateUrlInformation();
+
+if (!isset($_POST['operation'])) {
+ // if a GET variable is set then process the token upgrade
+ if (isset($_GET['token'])) {
+ updateAuthSubToken($_GET['token']);
+ } else {
+ if (loggingEnabled()) {
+ logMessage('reached operations.php without $_POST or $_GET variables set', 'error');
+ header('Location: index.php');
+ }
+ }
+}
+
+$operation = $_POST['operation'];
+
+switch ($operation) {
+
+ case 'create_upload_form':
+ createUploadForm($_POST['videoTitle'],
+ $_POST['videoDescription'],
+ $_POST['videoCategory'],
+ $_POST['videoTags']);
+ break;
+
+ case 'edit_meta_data':
+ editVideoData($_POST['newVideoTitle'],
+ $_POST['newVideoDescription'],
+ $_POST['newVideoCategory'],
+ $_POST['newVideoTags'],
+ $_POST['videoId']);
+ break;
+
+ case 'check_upload_status':
+ checkUpload($_POST['videoId']);
+ break;
+
+ case 'delete_video':
+ deleteVideo($_POST['videoId']);
+ break;
+
+ case 'auth_sub_request':
+ generateAuthSubRequestLink();
+ break;
+
+ case 'auth_sub_token_upgrade':
+ updateAuthSubToken($_GET['token']);
+ break;
+
+ case 'clear_session_var':
+ clearSessionVar($_POST['name']);
+ break;
+
+ case 'retrieve_playlists':
+ retrievePlaylists();
+ break;
+
+ case 'create_playlist':
+ createPlaylist($_POST['playlistTitle'], $_POST['playlistDescription']);
+ break;
+
+ case 'delete_playlist':
+ deletePlaylist($_POST['playlistTitle']);
+ break;
+
+ case 'update_playlist':
+ updatePlaylist($_POST['newPlaylistTitle'],
+ $_POST['newPlaylistDescription'],
+ $_POST['oldPlaylistTitle']);
+ break;
+
+ case (strcmp(substr($operation, 0, 7), 'search_') == 0):
+ // initialize search specific information
+ $searchType = substr($operation, 7);
+ searchVideos($searchType, $_POST['searchTerm'], $_POST['startIndex'],
+ $_POST['maxResults']);
+ break;
+
+ case 'show_video':
+ echoVideoPlayer($_POST['videoId']);
+ break;
+
+ default:
+ unsupportedOperation($_POST);
+ break;
+}
+
+/**
+ * Perform a search on youtube. Passes the result feed to echoVideoList.
+ *
+ * @param string $searchType The type of search to perform.
+ * If set to 'owner' then attempt to authenticate.
+ * @param string $searchTerm The term to search on.
+ * @param string $startIndex Start retrieving search results from this index.
+ * @param string $maxResults The number of results to retrieve.
+ * @return void
+ */
+function searchVideos($searchType, $searchTerm, $startIndex, $maxResults)
+{
+ // create an unauthenticated service object
+ $youTubeService = new Zend_Gdata_YouTube();
+ $query = $youTubeService->newVideoQuery();
+ $query->setQuery($searchTerm);
+ $query->setStartIndex($startIndex);
+ $query->setMaxResults($maxResults);
+
+ switch ($searchType) {
+ case 'most_viewed':
+ $query->setFeedType('most viewed');
+ $query->setTime('this_week');
+ $feed = $youTubeService->getVideoFeed($query);
+ break;
+ case 'most_recent':
+ $query->setFeedType('most recent');
+ $query->setTime('this_week');
+ $feed = $youTubeService->getVideoFeed($query);
+ break;
+ case 'recently_featured':
+ $query->setFeedType('recently featured');
+ $feed = $youTubeService->getVideoFeed($query);
+ break;
+ case 'top_rated':
+ $query->setFeedType('top rated');
+ $query->setTime('this_week');
+ $feed = $youTubeService->getVideoFeed($query);
+ break;
+ case 'username':
+ $feed = $youTubeService->getUserUploads($searchTerm);
+ break;
+ case 'all':
+ $feed = $youTubeService->getVideoFeed($query);
+ break;
+ case 'owner':
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+ try {
+ $feed = $youTubeService->getUserUploads('default');
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(),
+ 'response');
+ }
+ } catch (Zend_Gdata_App_HttpException $httpException) {
+ print 'ERROR ' . $httpException->getMessage()
+ . ' HTTP details<br /><textarea cols="100" rows="20">'
+ . $httpException->getRawResponseBody()
+ . '</textarea><br />'
+ . '<a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not retrieve users video feed: '
+ . $e->getMessage() . '<br />';
+ return;
+ }
+ echoVideoList($feed, true);
+ return;
+
+ default:
+ echo 'ERROR - Unknown search type - \'' . $searchType . '\'';
+ return;
+ }
+
+ if (loggingEnabled()) {
+ $httpClient = $youTubeService->getHttpClient();
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+ echoVideoList($feed);
+}
+
+/**
+ * Finds the URL for the flash representation of the specified video.
+ *
+ * @param Zend_Gdata_YouTube_VideoEntry $entry The video entry
+ * @return (string|null) The URL or null, if the URL is not found
+ */
+function findFlashUrl($entry)
+{
+ foreach ($entry->mediaGroup->content as $content) {
+ if ($content->type === 'application/x-shockwave-flash') {
+ return $content->url;
+ }
+ }
+ return null;
+}
+
+/**
+ * Check the upload status of a video
+ *
+ * @param string $videoId The video to check.
+ * @return string A message about the video's status.
+ */
+function checkUpload($videoId)
+{
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+
+ $feed = $youTubeService->getuserUploads('default');
+ $message = 'No further status information available yet.';
+
+ foreach($feed as $videoEntry) {
+ if ($videoEntry->getVideoId() == $videoId) {
+ // check if video is in draft status
+ try {
+ $control = $videoEntry->getControl();
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - not able to retrieve control element '
+ . $e->getMessage();
+ return;
+ }
+
+ if ($control instanceof Zend_Gdata_App_Extension_Control) {
+ if (($control->getDraft() != null) &&
+ ($control->getDraft()->getText() == 'yes')) {
+ $state = $videoEntry->getVideoState();
+ if ($state instanceof Zend_Gdata_YouTube_Extension_State) {
+ $message = 'Upload status: ' . $state->getName() . ' '
+ . $state->getText();
+ } else {
+ print $message;
+ }
+ }
+ }
+ }
+ }
+ print $message;
+}
+
+/**
+ * Store location of the demo application into session variables.
+ *
+ * @return void
+ */
+function generateUrlInformation()
+{
+ if (!isset($_SESSION['operationsUrl']) || !isset($_SESSION['homeUrl'])) {
+ $_SESSION['operationsUrl'] = 'http://'. $_SERVER['HTTP_HOST']
+ . $_SERVER['PHP_SELF'];
+ $path = explode('/', $_SERVER['PHP_SELF']);
+ $path[count($path)-1] = 'index.php';
+ $_SESSION['homeUrl'] = 'http://'. $_SERVER['HTTP_HOST']
+ . implode('/', $path);
+ }
+}
+
+/**
+ * Log a message to the session variable array.
+ *
+ * @param string $message The message to log.
+ * @param string $messageType The type of message to log.
+ * @return void
+ */
+function logMessage($message, $messageType)
+{
+ if (!isset($_SESSION['log_maxLogEntries'])) {
+ $_SESSION['log_maxLogEntries'] = 20;
+ }
+
+ if (!isset($_SESSION['log_currentCounter'])) {
+ $_SESSION['log_currentCounter'] = 0;
+ }
+
+ $currentCounter = $_SESSION['log_currentCounter'];
+ $currentCounter++;
+
+ if ($currentCounter > $_SESSION['log_maxLogEntries']) {
+ $_SESSION['log_currentCounter'] = 0;
+ }
+
+ $logLocation = 'log_entry_'. $currentCounter . '_' . $messageType;
+ $_SESSION[$logLocation] = $message;
+ $_SESSION['log_currentCounter'] = $currentCounter;
+}
+
+/**
+ * Update an existing video's meta-data.
+ *
+ * @param string $newVideoTitle The new title for the video entry.
+ * @param string $newVideoDescription The new description for the video entry.
+ * @param string $newVideoCategory The new category for the video entry.
+ * @param string $newVideoTags The new set of tags for the video entry (whitespace separated).
+ * @param string $videoId The video id for the video to be edited.
+ * @return void
+ */
+function editVideoData($newVideoTitle, $newVideoDescription, $newVideoCategory, $newVideoTags, $videoId)
+{
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+ $feed = $youTubeService->getVideoFeed('https://gdata.youtube.com/feeds/users/default/uploads');
+ $videoEntryToUpdate = null;
+
+ foreach($feed as $entry) {
+ if ($entry->getVideoId() == $videoId) {
+ $videoEntryToUpdate = $entry;
+ break;
+ }
+ }
+
+ if (!$videoEntryToUpdate instanceof Zend_Gdata_YouTube_VideoEntry) {
+ print 'ERROR - Could not find a video entry with id ' . $videoId
+ . '<br />' . printCacheWarning();
+ return;
+ }
+
+ try {
+ $putUrl = $videoEntryToUpdate->getEditLink()->getHref();
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not obtain video entry\'s edit link: '
+ . $e->getMessage() . '<br />';
+ return;
+ }
+
+ $videoEntryToUpdate->setVideoTitle($newVideoTitle);
+ $videoEntryToUpdate->setVideoDescription($newVideoDescription);
+ $videoEntryToUpdate->setVideoCategory($newVideoCategory);
+
+ // convert tags from space separated to comma separated
+ $videoTagsArray = explode(' ', trim($newVideoTags));
+
+ // strip out empty array elements
+ foreach($videoTagsArray as $key => $value) {
+ if (strlen($value) < 2) {
+ unset($videoTagsArray[$key]);
+ }
+ }
+
+ $videoEntryToUpdate->setVideoTags(implode(', ', $videoTagsArray));
+
+ try {
+ $updatedEntry = $youTubeService->updateEntry($videoEntryToUpdate, $putUrl);
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+ } catch (Zend_Gdata_App_HttpException $httpException) {
+ print 'ERROR ' . $httpException->getMessage()
+ . ' HTTP details<br /><textarea cols="100" rows="20">'
+ . $httpException->getRawResponseBody()
+ . '</textarea><br />'
+ . '<a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not post video meta-data: ' . $e->getMessage();
+ return;
+ }
+ print 'Entry updated successfully.<br /><a href="#" onclick="'
+ . 'ytVideoApp.presentFeed(\'search_owner\', 5, 0, \'none\'); '
+ . 'ytVideoApp.refreshSearchResults();" >'
+ . '(refresh your video listing)</a><br />'
+ . printCacheWarning();
+}
+
+/**
+ * Create upload form by sending the incoming video meta-data to youtube and
+ * retrieving a new entry. Prints form HTML to page.
+ *
+ * @param string $VideoTitle The title for the video entry.
+ * @param string $VideoDescription The description for the video entry.
+ * @param string $VideoCategory The category for the video entry.
+ * @param string $VideoTags The set of tags for the video entry (whitespace separated).
+ * @param string $nextUrl (optional) The URL to redirect back to after form upload has completed.
+ * @return void
+ */
+function createUploadForm($videoTitle, $videoDescription, $videoCategory, $videoTags, $nextUrl = null)
+{
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+ $newVideoEntry = new Zend_Gdata_YouTube_VideoEntry();
+
+ $newVideoEntry->setVideoTitle($videoTitle);
+ $newVideoEntry->setVideoDescription($videoDescription);
+
+ //make sure first character in category is capitalized
+ $videoCategory = strtoupper(substr($videoCategory, 0, 1))
+ . substr($videoCategory, 1);
+ $newVideoEntry->setVideoCategory($videoCategory);
+
+ // convert videoTags from whitespace separated into comma separated
+ $videoTagsArray = explode(' ', trim($videoTags));
+ $newVideoEntry->setVideoTags(implode(', ', $videoTagsArray));
+
+ $tokenHandlerUrl = 'https://gdata.youtube.com/action/GetUploadToken';
+ try {
+ $tokenArray = $youTubeService->getFormUploadToken($newVideoEntry, $tokenHandlerUrl);
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+ } catch (Zend_Gdata_App_HttpException $httpException) {
+ print 'ERROR ' . $httpException->getMessage()
+ . ' HTTP details<br /><textarea cols="100" rows="20">'
+ . $httpException->getRawResponseBody()
+ . '</textarea><br />'
+ . '<a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not retrieve token for syndicated upload. '
+ . $e->getMessage()
+ . '<br /><a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ }
+
+ $tokenValue = $tokenArray['token'];
+ $postUrl = $tokenArray['url'];
+
+ // place to redirect user after upload
+ if (!$nextUrl) {
+ $nextUrl = $_SESSION['homeUrl'];
+ }
+
+ print <<< END
+ <br /><form action="${postUrl}?nexturl=${nextUrl}"
+ method="post" enctype="multipart/form-data">
+ <input name="file" type="file"/>
+ <input name="token" type="hidden" value="${tokenValue}"/>
+ <input value="Upload Video File" type="submit" />
+ </form>
+END;
+}
+
+/**
+ * Deletes a Video.
+ *
+ * @param string $videoId Id of the video to be deleted.
+ * @return void
+ */
+function deleteVideo($videoId)
+{
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+ $feed = $youTubeService->getVideoFeed('https://gdata.youtube.com/feeds/users/default/uploads');
+ $videoEntryToDelete = null;
+
+ foreach($feed as $entry) {
+ if ($entry->getVideoId() == $videoId) {
+ $videoEntryToDelete = $entry;
+ break;
+ }
+ }
+
+ // check if videoEntryToUpdate was found
+ if (!$videoEntryToDelete instanceof Zend_Gdata_YouTube_VideoEntry) {
+ print 'ERROR - Could not find a video entry with id ' . $videoId . '<br />';
+ return;
+ }
+
+ try {
+ $httpResponse = $youTubeService->delete($videoEntryToDelete);
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+
+ } catch (Zend_Gdata_App_HttpException $httpException) {
+ print 'ERROR ' . $httpException->getMessage()
+ . ' HTTP details<br /><textarea cols="100" rows="20">'
+ . $httpException->getRawResponseBody()
+ . '</textarea><br />'
+ . '<a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not delete video: '. $e->getMessage();
+ return;
+ }
+
+ print 'Entry deleted succesfully.<br />' . $httpResponse->getBody()
+ . '<br /><a href="#" onclick="'
+ . 'ytVideoApp.presentFeed(\'search_owner\', 5, 0, \'none\');"'
+ . '">(refresh your video listing)</a><br />'
+ . printCacheWarning();
+}
+
+/**
+ * Enables logging.
+ *
+ * @param string $loggingOption 'on' to turn logging on, 'off' to turn logging off.
+ * @param integer|null $maxLogItems Maximum items to log, default is 10.
+ * @return void
+ */
+function setLogging($loggingOption, $maxLogItems = 10)
+{
+ switch ($loggingOption) {
+ case 'on' :
+ $_SESSION['logging'] = 'on';
+ $_SESSION['log_currentCounter'] = 0;
+ $_SESSION['log_maxLogEntries'] = $maxLogItems;
+ break;
+
+ case 'off':
+ $_SESSION['logging'] = 'off';
+ break;
+ }
+}
+
+/**
+ * Check whether logging is enabled.
+ *
+ * @return boolean Return true if session variable for logging is set to 'on'.
+ */
+function loggingEnabled()
+{
+ if ($_SESSION['logging'] == 'on') {
+ return true;
+ }
+}
+
+/**
+ * Unset a specific session variable.
+ *
+ * @param string $name Name of the session variable to delete.
+ * @return void
+ */
+function clearSessionVar($name)
+{
+ if (isset($_SESSION[$name])) {
+ unset($_SESSION[$name]);
+ }
+ header('Location: session_details.php');
+}
+
+/**
+ * Generate an AuthSub request Link and print it to the page.
+ *
+ * @param string $nextUrl URL to redirect to after performing the authentication.
+ * @return void
+ */
+function generateAuthSubRequestLink($nextUrl = null)
+{
+ $scope = 'https://gdata.youtube.com';
+ $secure = false;
+ $session = true;
+
+ if (!$nextUrl) {
+ generateUrlInformation();
+ $nextUrl = $_SESSION['operationsUrl'];
+ }
+
+ $url = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session);
+ echo '<a href="' . $url
+ . '"><strong>Click here to authenticate with YouTube</strong></a>';
+}
+
+/**
+ * Upgrade the single-use token to a session token.
+ *
+ * @param string $singleUseToken A valid single use token that is upgradable to a session token.
+ * @return void
+ */
+function updateAuthSubToken($singleUseToken)
+{
+ try {
+ $sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken);
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Token upgrade for ' . $singleUseToken
+ . ' failed : ' . $e->getMessage();
+ return;
+ }
+
+ $_SESSION['sessionToken'] = $sessionToken;
+ generateUrlInformation();
+ header('Location: ' . $_SESSION['homeUrl']);
+}
+
+/**
+ * Convenience method to obtain an authenticted Zend_Http_Client object.
+ *
+ * @return Zend_Http_Client An authenticated client.
+ */
+function getAuthSubHttpClient()
+{
+ try {
+ $httpClient = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']);
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not obtain authenticated Http client object. '
+ . $e->getMessage();
+ return;
+ }
+ $httpClient->setHeaders('X-GData-Key', 'key='. $_SESSION['developerKey']);
+ return $httpClient;
+}
+
+/**
+ * Echo img tags for the first thumbnail representing each video in the
+ * specified video feed. Upon clicking the thumbnails, the video should
+ * be presented.
+ *
+ * @param Zend_Gdata_YouTube_VideoFeed $feed The video feed
+ * @return void
+ */
+function echoThumbnails($feed)
+{
+ foreach ($feed as $entry) {
+ $videoId = $entry->getVideoId();
+ $firstThumbnail = htmlspecialchars(
+ $entry->mediaGroup->thumbnail[0]->url);
+ echo '<img id="' . $videoId . '" class="thumbnail" src="'
+ . $firstThumbnail .'" width="130" height="97" onclick="'
+ . 'ytVideoApp.presentVideo(\'' . $videoId . '\', 1);" '
+ . 'title="click to watch: ' .
+ htmlspecialchars($entry->getVideoTitle()) . '" />';
+ }
+}
+
+/**
+ * Echo the list of videos in the specified feed.
+ *
+ * @param Zend_Gdata_YouTube_VideoFeed $feed The video feed.
+ * @param boolean|null $authenticated If true then the videoList will
+ * attempt to create additional forms to edit video meta-data.
+ * @return void
+ */
+function echoVideoList($feed, $authenticated = false)
+{
+ $table = '<table id="videoResultList" class="videoList"><tbody>';
+ $results = 0;
+
+ foreach ($feed as $entry) {
+ $videoId = $entry->getVideoId();
+ $thumbnailUrl = 'notfound.jpg';
+ if (count($entry->mediaGroup->thumbnail) > 0) {
+ $thumbnailUrl = htmlspecialchars(
+ $entry->mediaGroup->thumbnail[0]->url);
+ }
+
+ $videoTitle = htmlspecialchars($entry->getVideoTitle());
+ $videoDescription = htmlspecialchars($entry->getVideoDescription());
+ $videoCategory = htmlspecialchars($entry->getVideoCategory());
+ $videoTags = $entry->getVideoTags();
+
+ $table .= '<tr id="video_' . $videoId . '">'
+ . '<td width="130"><img onclick="ytVideoApp.presentVideo(\''
+ . $videoId. '\')" src="' . $thumbnailUrl. '" /></td>'
+ . '<td><a href="#" onclick="ytVideoApp.presentVideo(\''
+ . $videoId . '\')">'. stripslashes($videoTitle) . '</a>'
+ . '<p class="videoDescription">'
+ . stripslashes($videoDescription) . '</p>'
+ . '<p class="videoCategory">category: ' . $videoCategory
+ . '</p><p class="videoTags">tagged: '
+ . htmlspecialchars(implode(', ', $videoTags)) . '</p>';
+
+ if ($authenticated) {
+ $table .= '<p class="edit">'
+ . '<a onclick="ytVideoApp.presentMetaDataEditForm(\''
+ . addslashes($videoTitle) . '\', \''
+ . addslashes($videoDescription) . '\', \''
+ . $videoCategory . '\', \''
+ . addslashes(implode(', ', $videoTags)) . '\', \''
+ . $videoId . '\');" href="#">edit video data</a> | '
+ . '<a href="#" onclick="ytVideoApp.confirmDeletion(\''
+ . $videoId
+ . '\');">delete this video</a></p><br clear="all">';
+ }
+
+ $table .= '</td></tr>';
+ $results++;
+ }
+
+ if ($results < 1) {
+ echo '<br />No results found<br /><br />';
+ } else {
+ echo $table .'</tbody></table><br />';
+ }
+}
+
+/**
+ * Echo the video embed code, related videos and videos owned by the same user
+ * as the specified videoId.
+ *
+ * @param string $videoId The video
+ * @return void
+ */
+function echoVideoPlayer($videoId)
+{
+ $youTubeService = new Zend_Gdata_YouTube();
+
+ try {
+ $entry = $youTubeService->getVideoEntry($videoId);
+ } catch (Zend_Gdata_App_HttpException $httpException) {
+ print 'ERROR ' . $httpException->getMessage()
+ . ' HTTP details<br /><textarea cols="100" rows="20">'
+ . $httpException->getRawResponseBody()
+ . '</textarea><br />'
+ . '<a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ }
+
+ $videoTitle = htmlspecialchars($entry->getVideoTitle());
+ $videoUrl = htmlspecialchars(findFlashUrl($entry));
+ $relatedVideoFeed = getRelatedVideos($entry->getVideoId());
+ $topRatedFeed = getTopRatedVideosByUser($entry->author[0]->name);
+
+ print <<<END
+ <b>$videoTitle</b><br />
+ <object width="425" height="350">
+ <param name="movie" value="${videoUrl}&autoplay=1"></param>
+ <param name="wmode" value="transparent"></param>
+ <embed src="${videoUrl}&autoplay=1" type="application/x-shockwave-flash" wmode="transparent"
+ width="425" height="350"></embed>
+ </object>
+END;
+
+ echo '<br />';
+ echoVideoMetadata($entry);
+ echo '<br /><b>Related:</b><br />';
+ echoThumbnails($relatedVideoFeed);
+ echo '<br /><b>Top rated videos by user:</b><br />';
+ echoThumbnails($topRatedFeed);
+}
+
+/**
+ * Returns a feed of videos related to the specified video
+ *
+ * @param string $videoId The video
+ * @return Zend_Gdata_YouTube_VideoFeed The feed of related videos
+ */
+function getRelatedVideos($videoId)
+{
+ $youTubeService = new Zend_Gdata_YouTube();
+ $ytQuery = $youTubeService->newVideoQuery();
+ // show videos related to the specified video
+ $ytQuery->setFeedType('related', $videoId);
+ // order videos by rating
+ $ytQuery->setOrderBy('rating');
+ // retrieve a maximum of 5 videos
+ $ytQuery->setMaxResults(5);
+ // retrieve only embeddable videos
+ $ytQuery->setFormat(5);
+ return $youTubeService->getVideoFeed($ytQuery);
+}
+
+/**
+ * Returns a feed of top rated videos for the specified user
+ *
+ * @param string $user The username
+ * @return Zend_Gdata_YouTube_VideoFeed The feed of top rated videos
+ */
+function getTopRatedVideosByUser($user)
+{
+ $userVideosUrl = 'https://gdata.youtube.com/feeds/users/' .
+ $user . '/uploads';
+ $youTubeService = new Zend_Gdata_YouTube();
+ $ytQuery = $youTubeService->newVideoQuery($userVideosUrl);
+ // order by the rating of the videos
+ $ytQuery->setOrderBy('rating');
+ // retrieve a maximum of 5 videos
+ $ytQuery->setMaxResults(5);
+ // retrieve only embeddable videos
+ $ytQuery->setFormat(5);
+ return $youTubeService->getVideoFeed($ytQuery);
+}
+
+/**
+ * Echo video metadata
+ *
+ * @param Zend_Gdata_YouTube_VideoEntry $entry The video entry
+ * @return void
+ */
+function echoVideoMetadata($entry)
+{
+ $title = htmlspecialchars($entry->getVideoTitle());
+ $description = htmlspecialchars($entry->getVideoDescription());
+ $authorUsername = htmlspecialchars($entry->author[0]->name);
+ $authorUrl = 'http://www.youtube.com/profile?user=' .
+ $authorUsername;
+ $tags = htmlspecialchars(implode(', ', $entry->getVideoTags()));
+ $duration = htmlspecialchars($entry->getVideoDuration());
+ $watchPage = htmlspecialchars($entry->getVideoWatchPageUrl());
+ $viewCount = htmlspecialchars($entry->getVideoViewCount());
+ $rating = 0;
+ if (isset($entry->rating->average)) {
+ $rating = $entry->rating->average;
+ }
+ $numRaters = 0;
+ if (isset($entry->rating->numRaters)) {
+ $numRaters = $entry->rating->numRaters;
+ }
+ $flashUrl = htmlspecialchars(findFlashUrl($entry));
+ print <<<END
+ <b>Title:</b> ${title}<br />
+ <b>Description:</b> ${description}<br />
+ <b>Author:</b> <a href="${authorUrl}">${authorUsername}</a><br />
+ <b>Tags:</b> ${tags}<br />
+ <b>Duration:</b> ${duration} seconds<br />
+ <b>View count:</b> ${viewCount}<br />
+ <b>Rating:</b> ${rating} (${numRaters} ratings)<br />
+ <b>Flash:</b> <a href="${flashUrl}">${flashUrl}</a><br />
+ <b>Watch page:</b> <a href="${watchPage}">${watchPage}</a> <br />
+END;
+}
+
+/**
+ * Print message about YouTube caching.
+ *
+ * @return string A message
+ */
+function printCacheWarning()
+{
+ return '<p class="note">'
+ . 'Please note that the change may not be reflected in the API '
+ . 'immediately due to caching.<br/>'
+ . 'Please refer to the API documentation for more details.</p>';
+}
+
+/**
+ * Retrieve playlists for the currently authenticated user and print.
+ * @return void
+ */
+function retrievePlaylists()
+{
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+ $feed = $youTubeService->getPlaylistListFeed('default');
+
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+
+ if (!$feed instanceof Zend_Gdata_YouTube_PlaylistListFeed) {
+ print 'ERROR - Could not retrieve playlists<br />'.
+ printCacheWarning();
+ return;
+ }
+
+ $playlistEntries = '<ul>';
+ $entriesFound = 0;
+ foreach($feed as $entry) {
+ $playlistTitle = $entry->getTitleValue();
+ $playlistDescription = $entry->getDescription()->getText();
+ $playlistEntries .= '<li><h3>' . $playlistTitle
+ . '</h3>' . $playlistDescription . ' | '
+ . '<a href="#" onclick="ytVideoApp.prepareUpdatePlaylistForm(\''
+ . $playlistTitle . '\', \'' . $playlistDescription
+ . '\'); ">update</a> | '
+ . '<a href="#" onclick="ytVideoApp.confirmPlaylistDeletion(\''
+ . $playlistTitle . '\');">delete</a></li>';
+ $entriesFound++;
+ }
+
+ $playlistEntries .= '</ul><br /><a href="#" '
+ . 'onclick="ytVideoApp.prepareCreatePlaylistForm(); '
+ . 'return false;">'
+ . 'Add new playlist</a><br />'
+ . '<div id="addNewPlaylist"></div>';
+
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+ if ($entriesFound > 0) {
+ print $playlistEntries;
+ } else {
+ print 'No playlists found';
+ }
+}
+
+/**
+ * Create a new playlist for the currently authenticated user
+ *
+ * @param string $playlistTitle Title of the new playlist
+ * @param string $playlistDescription Description for the new playlist
+ * @return void
+ */
+function createPlaylist($playlistTitle, $playlistDescription)
+{
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+ $feed = $youTubeService->getPlaylistListFeed('default');
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+
+ $newPlaylist = $youTubeService->newPlaylistListEntry();
+ $newPlaylist->description = $youTubeService->newDescription()->setText($playlistDescription);
+ $newPlaylist->title = $youTubeService->newTitle()->setText($playlistDescription);
+
+ if (!$feed instanceof Zend_Gdata_YouTube_PlaylistListFeed) {
+ print 'ERROR - Could not retrieve playlists<br />'
+ . printCacheWarning();
+ return;
+ }
+
+ $playlistFeedUrl = 'https://gdata.youtube.com/feeds/users/default/playlists';
+
+ try {
+ $updatedEntry = $youTubeService->insertEntry($newPlaylist, $playlistFeedUrl);
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+ } catch (Zend_Gdata_App_HttpException $httpException) {
+ print 'ERROR ' . $httpException->getMessage()
+ . ' HTTP details<br /><textarea cols="100" rows="20">'
+ . $httpException->getRawResponseBody()
+ . '</textarea><br />'
+ . '<a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not create new playlist: ' . $e->getMessage();
+ return;
+ }
+
+ print 'Playlist added succesfully.<br /><a href="#" onclick="'
+ . 'ytVideoApp.retrievePlaylists();"'
+ . '">(refresh your playlist listing)</a><br />'
+ . printCacheWarning();
+}
+
+/**
+ * Delete a playlist
+ *
+ * @param string $playlistTitle Title of the playlist to be deleted
+ * @return void
+ */
+function deletePlaylist($playlistTitle)
+{
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+ $feed = $youTubeService->getPlaylistListFeed('default');
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+
+ $playlistEntryToDelete = null;
+
+ foreach($feed as $playlistEntry) {
+ if ($playlistEntry->getTitleValue() == $playlistTitle) {
+ $playlistEntryToDelete = $playlistEntry;
+ break;
+ }
+ }
+
+ if (!$playlistEntryToDelete instanceof Zend_Gdata_YouTube_PlaylistListEntry) {
+ print 'ERROR - Could not retrieve playlist to be deleted<br />'
+ . printCacheWarning();
+ return;
+ }
+
+ try {
+ $response = $playlistEntryToDelete->delete();
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+ } catch (Zend_Gdata_App_HttpException $httpException) {
+ print 'ERROR ' . $httpException->getMessage()
+ . ' HTTP details<br /><textarea cols="100" rows="20">'
+ . $httpException->getRawResponseBody()
+ . '</textarea><br />'
+ . '<a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not delete the playlist: ' . $e->getMessage();
+ return;
+ }
+
+ print 'Playlist deleted succesfully.<br />'
+ . '<a href="#" onclick="ytVideoApp.retrievePlaylists();">'
+ . '(refresh your playlist listing)</a><br />' . printCacheWarning();
+}
+
+/**
+ * Delete a playlist
+ *
+ * @param string $newplaylistTitle New title for the playlist to be updated
+ * @param string $newPlaylistDescription New description for the playlist to be updated
+ * @param string $oldPlaylistTitle Title of the playlist to be updated
+ * @return void
+ */
+function updatePlaylist($newPlaylistTitle, $newPlaylistDescription, $oldPlaylistTitle)
+{
+ $httpClient = getAuthSubHttpClient();
+ $youTubeService = new Zend_Gdata_YouTube($httpClient);
+ $feed = $youTubeService->getPlaylistListFeed('default');
+
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+
+ $playlistEntryToDelete = null;
+
+ foreach($feed as $playlistEntry) {
+ if ($playlistEntry->getTitleValue() == $oldplaylistTitle) {
+ $playlistEntryToDelete = $playlistEntry;
+ break;
+ }
+ }
+
+ if (!$playlistEntryToDelete instanceof Zend_Gdata_YouTube_PlaylistListEntry) {
+ print 'ERROR - Could not retrieve playlist to be updated<br />'
+ . printCacheWarning();
+ return;
+ }
+
+ try {
+ $response = $playlistEntryToDelete->delete();
+ if (loggingEnabled()) {
+ logMessage($httpClient->getLastRequest(), 'request');
+ logMessage($httpClient->getLastResponse()->getBody(), 'response');
+ }
+ } catch (Zend_Gdata_App_HttpException $httpException) {
+ print 'ERROR ' . $httpException->getMessage()
+ . ' HTTP details<br /><textarea cols="100" rows="20">'
+ . $httpException->getRawResponseBody()
+ . '</textarea><br />'
+ . '<a href="session_details.php">'
+ . 'click here to view details of last request</a><br />';
+ return;
+ } catch (Zend_Gdata_App_Exception $e) {
+ print 'ERROR - Could not delete the playlist: ' . $e->getMessage();
+ return;
+ }
+
+ print 'Playlist deleted succesfully.<br /><a href="#" onclick="' .
+ 'ytVideoApp.retrievePlaylists();"'.
+ '">(refresh your playlist listing)</a><br />'.
+ printCacheWarning();
+}
+
+/**
+ * Helper function if an unsupported operation is passed into this files main loop.
+ *
+ * @param array $post (Optional) The post variables that accompanied the operation, if available.
+ * @return void
+ */
+function unsupportedOperation($post)
+{
+ $message = 'ERROR An unsupported operation has been called - post variables received '
+ . print_r($post, true);
+
+ if (loggingEnabled()) {
+ logMessage($message, 'error');
+ }
+ print $message;
+}
+
+?>
diff --git a/zend/demos/Zend/Gdata/YouTubeVideoApp/session_details.php b/zend/demos/Zend/Gdata/YouTubeVideoApp/session_details.php
new file mode 100755
index 0000000..dd4e996
--- /dev/null
+++ b/zend/demos/Zend/Gdata/YouTubeVideoApp/session_details.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * 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
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * PHP sample code for the YouTube data API. Utilizes the Zend Framework
+ * Zend_Gdata component to communicate with the YouTube data API.
+ *
+ * Requires the Zend Framework Zend_Gdata component and PHP >= 5.2.11
+ * This sample is run from within a web browser. These files are required:
+ * session_details.php - a script to view log output and session variables
+ * operations.php - the main logic, which interfaces with the YouTube API
+ * index.php - the HTML to represent the web UI, contains some PHP
+ * video_app.css - the CSS to define the interface style
+ * video_app.js - the JavaScript used to provide the video list AJAX interface
+ *
+ * NOTE: If using in production, some additional precautions with regards
+ * to filtering the input data should be used. This code is designed only
+ * for demonstration purposes.
+ */
+session_start();
+?>
+<html>
+<head>
+ <title>YouTube data API Video Browser in PHP - Session Viewer</title>
+ <link href="video_app.css" type="text/css" rel="stylesheet"/>
+ <script src="video_app.js" type="text/javascript"></script>
+</head>
+<body>
+<div id="mainSessions">
+ <div id="titleBar">
+ <div id="titleText"><h3>Session variables</h3></div><br clear="all" />
+ </div>
+<?php
+
+$session_copy = $_SESSION;
+ksort($session_copy);
+
+foreach($session_copy as $key => $value) {
+
+ print '<h3>'. $key . '</h3><div id="sessionVariable" >'. $value .'</div><br />'.
+ '<form method="POST" action="operations.php">' .
+ '<input type="hidden" value="clear_session_var" name="operation"/>'.
+ '<input type="hidden" name="name" value="'. $key .'"/>'.
+ '<input type="submit" value="click to delete"/></form><hr />';
+}
+?>
+<br clear="both" />
+<a href="index.php">back</a>
+ </div></body></html>
diff --git a/zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.css b/zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.css
new file mode 100755
index 0000000..0e4a743
--- /dev/null
+++ b/zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.css
@@ -0,0 +1,236 @@
+body {
+ background-color: #fff;
+ color: #232323;
+ font-family: Arial, sans-serif;
+ font-size: small;
+ margin: 8px;
+ margin-top: 3px;
+}
+
+/* TODO jhartman --> swap out with css from app engine apps
+*/
+
+
+img {
+ border: 0;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+th, td {
+ padding: 0;
+ vertical-align: top;
+ text-align: left;
+}
+
+a:link {
+ color: #0000cc;
+}
+
+a:active {
+ color: #cc0000;
+}
+
+a:visited {
+ color: #551a8b;
+}
+
+h1 {
+ font-size: x-large;
+ margin-top: 0px;
+ margin-bottom: 5px;
+}
+
+h2 {
+ font-size: large;
+}
+
+h3 {
+ font-size: medium;
+}
+
+h4 {
+ font-size: small;
+}
+
+form {
+ display: inline;
+ margin: 0;
+ padding: 0;
+}
+
+li {
+ margin-bottom: 0.25em;
+}
+
+pre, code {
+ color: #007000;
+ font-family: "bogus font here", monospace;
+ font-size: 100%;
+}
+
+pre {
+ border: 1px solid silver;
+ background-color: #f5f5f5;
+ padding: 0.5em;
+ overflow: auto;
+ margin: 2em;
+}
+
+pre ins {
+ color: #cc0000;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+/* forms */
+textarea {
+ width: 600px;
+ border: 1px solid #ddd;
+ padding: 5px;
+}
+
+.submit {
+ border: 1px solid #ddd;
+}
+
+input, select{
+ border: 1px solid #ddd;
+ margin-bottom: 2px;
+}
+
+hr {
+ border: none;
+ border-bottom: 1px solid #ddd;
+}
+
+/* "Selected" links */
+a.selected, .selected a, .selected {
+ color: black;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+a.selected:visited, .selected a:visited {
+ color: black;
+}
+
+p.videoDescription {
+ margin: 0;
+ padding: 0;
+ overflow: scroll;
+ font-size: small;
+}
+
+p.videoCategory {
+ margin: 0;
+ padding: 0;
+ /* overflow: scroll; */
+ font-size: x-small;
+}
+
+p.videoTags {
+ margin: 0;
+ padding: 0;
+ /* overflow: scroll; */
+ font-size: x-small;
+}
+
+p.edit {
+ font-size: small;
+}
+
+.note {
+ padding: 2px;
+ background-color: yellow;
+ color: #000;
+}
+
+#editForm {
+ font-size: small;
+}
+
+table.videoList {
+ width: 100%;
+}
+
+.videoList td {
+ padding: 10px 0px 5px 5px;
+ border-bottom: 1px solid silver;
+}
+
+#titleBar {
+ border: 1px solid silver;
+ background-color: #e5ecf9;
+ margin: 0;
+ padding: 0;
+ padding-top: 5px;
+ padding-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ margin-top: 5px;
+ margin-bottom: 15px;
+}
+
+#titleText {
+ float: left;
+}
+
+#searchBox {
+ float: right;
+}
+
+#authStatus {
+ border-bottom: 1px solid #ddd;
+ padding: 2px;
+ margin-bottom: 10px;
+
+}
+
+#main {
+ margin: 10px;
+}
+
+#mainSessions {
+ background-color: #ddd;
+ padding: 10px;
+}
+
+#searchResults {
+ width: 100%;
+ background-color: silver;
+}
+
+#searchResultsListColumn {
+ float: left;
+ width: 47%;
+ margin-bottom: 20px;
+ padding-right: 2px;
+}
+
+#searchResultsVideoColumn {
+ float: right;
+ width: 47%;
+ padding-left: 5px;
+ border-left: 1px solid #ddd;
+
+}
+
+#sessionVariable {
+ font-family: Courier, monospace;
+ background-color: #fff;
+ padding: 10px;
+ width: 80%;
+ overflow: scroll;
+}
+
+.thumbnail {
+ padding: 0px 0px 0px 2px;
+}
+
+#imageLoadThumbnail {
+ padding: 4px;
+ background-color: #333;
+}
diff --git a/zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.js b/zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.js
new file mode 100755
index 0000000..c01d806
--- /dev/null
+++ b/zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.js
@@ -0,0 +1,582 @@
+/**
+ * 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
+ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @fileoverview Provides functions for browsing and searching YouTube
+ * data API feeds, as well as performing authentication, syndicated uploads
+ * and playlist management using a PHP backend powered by the Zend_Gdata component
+ * of Zend Framework.
+ */
+
+/**
+ * provides namespacing for the YouTube Video Application PHP version (ytVideoApp)
+ */
+var ytVideoApp = {};
+
+/**
+ * maximum number of results to return for list of videos
+ * @type Number
+ */
+ytVideoApp.MAX_RESULTS_LIST = 5;
+
+/**
+ * navigation button id used to page to the previous page of
+ * results in the list of videos
+ * @type String
+ */
+ytVideoApp.PREVIOUS_PAGE_BUTTON = 'previousPageButton';
+
+/**
+ * navigation button id used to page to the next page of
+ * results in the list of videos
+ * @type String
+ */
+ytVideoApp.NEXT_PAGE_BUTTON = 'nextPageButton';
+
+/**
+ * container div for navigation elements
+ * @type String
+ */
+ytVideoApp.NAVIGATION_DIV = 'navigationForm';
+
+/**
+ * container div id used to hold list of videos
+ * @type String
+ */
+ytVideoApp.VIDEO_LIST_CONTAINER_DIV = 'searchResultsVideoList';
+
+/**
+ * container div id used to hold video search results
+ * @type String
+ */
+ytVideoApp.VIDEO_SEARCH_RESULTS_DIV = 'searchResultsVideoColumn';
+
+/**
+ * container div id used to hold the video player
+ * @type String
+ */
+ytVideoApp.VIDEO_PLAYER_DIV = 'videoPlayer';
+
+/**
+ * container div id used to hold the search box displayed at the top of
+ * the browser after one search has already been performed
+ * @type String
+ */
+ytVideoApp.TOP_SEARCH_CONTAINER_DIV = 'searchBox';
+
+/** container div to show detailed upload status
+ * @type String
+ */
+ytVideoApp.VIDEO_UPLOAD_STATUS = 'detailedUploadStatus';
+
+/**
+ * container div to hold the form for syndicated upload
+ * @type String
+ */
+ytVideoApp.SYNDICATED_UPLOAD_DIV = 'syndicatedUploadDiv';
+
+/**
+ * container div to hold the form to edit video meta-data
+ * @type String
+ */
+ytVideoApp.VIDEO_DATA_EDIT_DIV = 'editForm';
+
+/**
+ * containder div to hold authentication link in special cases where auth gets
+ * set prior to developer key
+ * @type String
+ */
+ytVideoApp.AUTHSUB_REQUEST_DIV = 'generateAuthSubLink';
+
+/**
+ * container div to hold the form for editing video meta-data
+ * @type String
+ */
+ytVideoApp.VIDEO_META_DATA_EDIT_DIV = 'editVideoMetaDataDiv';
+
+/**
+ * container div to hold the form for adding a new playlist
+ * @type String
+ */
+ytVideoApp.PLAYLIST_ADD_DIV = 'addNewPlaylist';
+
+/**
+ * the page number to use for the next page navigation button
+ * @type Number
+ */
+ytVideoApp.nextPage = 2;
+
+/**
+ * the page number to use for the previous page navigation button
+ * @type Number
+ */
+ytVideoApp.previousPage = 0;
+
+/**
+ * the last search term used to query - allows for the navigation
+ * buttons to know what string query to perform when clicked
+ * @type String
+ */
+ytVideoApp.previousSearchTerm = '';
+
+/**
+ * the last query type used for querying - allows for the navigation
+ * buttons to know what type of query to perform when clicked
+ * @type String
+ */
+ytVideoApp.previousQueryType = 'all';
+
+/**
+ * Retrieves a list of videos matching the provided criteria. The list of
+ * videos can be restricted to a particular standard feed or search criteria.
+ * @param {String} op The type of action to be done.
+ * for querying all videos, or the name of a standard feed.
+ * @param {String} searchTerm The search term(s) to use for querying as the
+ * 'vq' query parameter value
+ * @param {Number} page The 1-based page of results to return.
+ */
+ytVideoApp.listVideos = function(op, searchTerm, page) {
+ ytVideoApp.previousSearchTerm = searchTerm;
+ ytVideoApp.previousQueryType = op;
+ var maxResults = ytVideoApp.MAX_RESULTS_LIST;
+ var startIndex = (((page - 1) * ytVideoApp.MAX_RESULTS_LIST) + 1);
+ ytVideoApp.presentFeed(op, maxResults, startIndex, searchTerm);
+ ytVideoApp.updateNavigation(page);
+};
+
+/**
+ * Sends an AJAX request to the server to retrieve a list of videos or
+ * the video player/metadata. Sends the request to the specified filePath
+ * on the same host, passing the specified params, and filling the specified
+ * resultDivName with the resutls upon success.
+ * @param {String} filePath The path to which the request should be sent
+ * @param {String} params The URL encoded POST params
+ * @param {String} resultDivName The name of the DIV used to hold the results
+ */
+ytVideoApp.sendRequest = function(filePath, params, resultDivName) {
+ if (window.XMLHttpRequest) {
+ var xmlhr = new XMLHttpRequest();
+ } else {
+ var xmlhr = new ActiveXObject('MSXML2.XMLHTTP.3.0');
+ }
+
+ xmlhr.open('POST', filePath);
+ xmlhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+
+ xmlhr.onreadystatechange = function() {
+ var resultDiv = document.getElementById(resultDivName);
+ if (xmlhr.readyState == 1) {
+ resultDiv.innerHTML = '<b>Loading...</b>';
+ } else if (xmlhr.readyState == 4 && xmlhr.status == 200) {
+ if (xmlhr.responseText) {
+ resultDiv.innerHTML = xmlhr.responseText;
+ }
+ } else if (xmlhr.readyState == 4) {
+ alert('Invalid response received - Status: ' + xmlhr.status);
+ }
+ }
+ xmlhr.send(params);
+}
+
+/**
+ * Uses ytVideoApp.sendRequest to display a YT video player and metadata for the
+ * specified video ID.
+ * @param {String} videoId The ID of the YouTube video to show
+ */
+ytVideoApp.presentVideo = function(videoId, updateThumbnail) {
+ var params = 'operation=show_video&videoId=' + videoId;
+ var filePath = 'operations.php';
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_PLAYER_DIV);
+}
+
+/**
+ * Creates a form to enter video meta-data in preparation for syndicated upload.
+ */
+ytVideoApp.prepareUploadForm = function() {
+ var metaDataForm = ['<br clear="all"><form id="uploadForm" ',
+ 'onsubmit="ytVideoApp.prepareSyndicatedUpload(',
+ 'this.videoTitle.value, ',
+ 'this.videoDescription.value, ',
+ 'this.videoCategory.value, ',
+ 'this.videoTags.value); ',
+ 'return false;">',
+ 'Enter video title:<br /><input size="50" name="videoTitle" ',
+ 'type="text" /><br />',
+ 'Enter video description:<br /><textarea cols="50" ',
+ 'name="videoDescription"></textarea><br />',
+ 'Select a category: <select name="videoCategory">',
+ '<option value="Autos">Autos &amp; Vehicles</option>',
+ '<option value="Music">Music</option>',
+ '<option value="Animals">Pets &amp; Animals</option>',
+ '<option value="Sports">Sports</option>',
+ '<option value="Travel">Travel &amp; Events</option>',
+ '<option value="Games">Gadgets &amp; Games</option>',
+ '<option value="Comedy">Comedy</option>',
+ '<option value="People">People &amp; Blogs</option>',
+ '<option value="News">News &amp; Politics</option>',
+ '<option value="Entertainment">Entertainment</option>',
+ '<option value="Education">Education</option>',
+ '<option value="Howto">Howto &amp; Style</option>',
+ '<option value="Nonprofit">Nonprofit &amp; Activism</option>',
+ '<option value="Tech">Science &amp; Technology</option>',
+ '</select><br />',
+ 'Enter some tags to describe your video ',
+ '<em>(separated by spaces)</em>:<br />',
+ '<input name="videoTags" type="text" size="50" value="video" /><br />',
+ '<input type="submit" value="go">',
+ '</form>'].join('');
+
+ document.getElementById(ytVideoApp.SYNDICATED_UPLOAD_DIV).innerHTML = metaDataForm;
+}
+
+/**
+ * Uses ytVideoApp.sendRequest to prepare a syndicated upload.
+ *
+ * @param {String} videoTitle The title for new video
+ * @param {String} videoDescription The video's description
+ * @param {String} videoCategory The category for the video
+ * @param {String} videoTags A white-space separated string of Tags
+ */
+ytVideoApp.prepareSyndicatedUpload = function(videoTitle, videoDescription, videoCategory, videoTags) {
+ var filePath = 'operations.php';
+ var params = 'operation=create_upload_form' +
+ '&videoTitle=' + videoTitle +
+ '&videoDescription=' + videoDescription +
+ '&videoCategory=' + videoCategory +
+ '&videoTags=' + videoTags;
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.SYNDICATED_UPLOAD_DIV);
+}
+
+/**
+ * Uses ytVideoApp.sendRequest to create the authSub link.
+ */
+ytVideoApp.presentAuthLink = function() {
+ var filePath = 'operations.php';
+ var params = 'operation=auth_sub_request';
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.AUTHSUB_REQUEST_DIV);
+}
+
+
+/**
+ * Uses ytVideoApp.sendRequest to check a videos upload status.
+ *
+ * @param {String} videoId The id of the video to check
+ */
+ytVideoApp.checkUploadDetails = function(videoId) {
+ var filePath = 'operations.php';
+ var params = 'operation=check_upload_status' +
+ '&videoId=' + videoId;
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_UPLOAD_STATUS);
+}
+
+
+/**
+ * Creates an HTML form to edit a video's meta-data, populated with the
+ * videos current meta-data.
+ *
+ * @param {String} oldVideoTitle The old title of the video
+ * @param {String} oldVideoDescription The old description of the video
+ * @param {String} oldVideoCategory The old category of the video
+ * @param {String} oldVideoTags The old tags for the video (separated by white-space)
+ * @param {String} videoId The id of the video to be edited
+ */
+ytVideoApp.presentMetaDataEditForm = function(oldVideoTitle, oldVideoDescription, oldVideoCategory, oldVideoTags, videoId) {
+ // split oldVideoTags by comma and present as whitespace separated
+ var oldVideoTagsArray = oldVideoTags.split(',');
+ oldVideoTags = oldVideoTagsArray.join(' ');
+ var editMetaDataForm = ['<form id="editForm" ',
+ 'onsubmit="ytVideoApp.editMetaData(',
+ 'this.newVideoTitle.value, ',
+ 'this.newVideoDescription.value, ',
+ 'this.newVideoCategory.value, ',
+ 'this.newVideoTags.value, ',
+ 'this.videoId.value);',
+ 'return false;">',
+ 'Enter a new video title:<br />',
+ '<input size="50" name="newVideoTitle" ',
+ 'type="text" value="',
+ oldVideoTitle,
+ '"/><br />',
+ 'Enter a new video description:<br />',
+ '<textarea cols="50" name="newVideoDescription">',
+ oldVideoDescription,
+ '</textarea><br />',
+ 'Select a new category: <select ',
+ 'name="newVideoCategory">',
+ '<option value="Autos">Autos &amp; Vehicles</option>',
+ '<option value="Music">Music</option>',
+ '<option value="Animals">Pets &amp; Animals</option>',
+ '<option value="Sports">Sports</option>',
+ '<option value="Travel">Travel &amp; Events</option>',
+ '<option value="Games">Gadgets &amp; Games</option>',
+ '<option value="Comedy">Comedy</option>',
+ '<option value="People">People &amp; Blogs</option>',
+ '<option value="News">News &amp; Politics</option>',
+ '<option value="Entertainment">Entertainment</option>',
+ '<option value="Education">Education</option>',
+ '<option value="Howto">Howto &amp; Style</option>',
+ '<option value="Nonprofit">Nonprofit &amp; Activism</option>',
+ '<option value="Tech">Science &amp; Technology</option>',
+ '</select><br />',
+ 'Enter some new tags to describe your video ',
+ '<em>(separated by spaces)</em>:<br />',
+ '<input name="newVideoTags" type="text" size="50" ',
+ 'value="',
+ oldVideoTags,
+ '"/><br />',
+ '<input name="videoId" type="hidden" value="',
+ videoId,
+ '" /><br />',
+ '<input type="submit" value="go">',
+ '</form>'].join('');
+
+ document.getElementById(ytVideoApp.VIDEO_SEARCH_RESULTS_DIV).innerHTML = editMetaDataForm;
+}
+
+/**
+ * Uses ytVideoApp.sendRequest to submit updated video meta-data.
+ *
+ * @param {String} newVideoTitle The new title of the video
+ * @param {String} newVideoDescription The new description of the video
+ * @param {String} newVideoCategory The new category of the video
+ * @param {String} newVideoTags The new tags for the video (separated by white-space)
+ * @param {String} videoId The id of the video to be edited
+ */
+ytVideoApp.editMetaData = function(newVideoTitle, newVideoDescription, newVideoCategory, newVideoTags, videoId) {
+ var filePath = 'operations.php';
+ var params = 'operation=edit_meta_data' +
+ '&newVideoTitle=' + newVideoTitle +
+ '&newVideoDescription=' + newVideoDescription +
+ '&newVideoCategory=' + newVideoCategory +
+ '&newVideoTags=' + newVideoTags +
+ '&videoId=' + videoId;
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_SEARCH_RESULTS_DIV);
+};
+
+
+/**
+ * Confirms whether user wants to delete a video.
+ * @param {String} videoId The video Id to be deleted
+ */
+ytVideoApp.confirmDeletion = function(videoId) {
+ var answer = confirm('Do you really want to delete the video with id: ' + videoId + ' ?');
+ if (answer) {
+ ytVideoApp.prepareDeletion(videoId);
+ }
+}
+
+/**
+ * Uses ytVideoApp.sendRequest to request a video to be deleted.
+ * @param {String} videoId The video Id to be deleted
+ */
+ytVideoApp.prepareDeletion = function(videoId) {
+ var filePath = 'operations.php';
+ var params = 'operation=delete_video' +
+ '&videoId=' + videoId;
+
+ var table = document.getElementById('videoResultList');
+ var indexOfRowToBeDeleted = -1;
+ var tableRows = document.getElementsByTagName('TR');
+ for (var i = 0, tableRow; tableRow = tableRows[i]; i++) {
+ if (tableRow.id == videoId) {
+ indexOfRowToBeDeleted = i;
+ }
+ }
+ if (indexOfRowToBeDeleted > -1) {
+ table.deleteRow(indexOfRowToBeDeleted);
+ }
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_SEARCH_RESULTS_DIV);
+}
+
+/**
+ * Uses ytVideoApp.sendRequest to display a list of of YT videos.
+ * @param {String} op The operation to perform to retrieve a feed
+ * @param {Number} maxResults The maximum number of videos to list
+ * @param {Number} startIndex The first video to include in the list
+ * @param {String} searchTerm The search terms to pass to the specified feed
+ */
+ytVideoApp.presentFeed = function(op, maxResults, startIndex, searchTerm){
+ var params = 'operation=' + op +
+ '&maxResults=' + maxResults +
+ '&startIndex=' + startIndex +
+ '&searchTerm=' + searchTerm;
+ var filePath = 'operations.php';
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_LIST_CONTAINER_DIV);
+};
+
+/**
+ * Updates the variables used by the navigation buttons and the 'enabled'
+ * status of the buttons based upon the current page number passed in.
+ * @param {Number} page The current page number
+ */
+ytVideoApp.updateNavigation = function(page) {
+ ytVideoApp.nextPage = page + 1;
+ ytVideoApp.previousPage = page - 1;
+ document.getElementById(ytVideoApp.NEXT_PAGE_BUTTON).style.display = 'inline';
+ document.getElementById(ytVideoApp.PREVIOUS_PAGE_BUTTON).style.display = 'inline';
+ if (ytVideoApp.previousPage < 1) {
+ document.getElementById(ytVideoApp.PREVIOUS_PAGE_BUTTON).disabled = true;
+ } else {
+ document.getElementById(ytVideoApp.PREVIOUS_PAGE_BUTTON).disabled = false;
+ }
+ document.getElementById(ytVideoApp.NEXT_PAGE_BUTTON).disabled = false;
+};
+
+/**
+ * Hides the navigation.
+ */
+ytVideoApp.hideNavigation = function() {
+ document.getElementById(ytVideoApp.NAVIGATION_DIV).style.display = 'none';
+};
+
+/**
+ * Update video results div
+ */
+ytVideoApp.refreshSearchResults = function() {
+ document.getElementById(ytVideoApp.VIDEO_SEARCH_RESULTS_DIV).innerHTML = '';
+}
+
+/**
+ * Method called when the query type has been changed. Clears out the
+ * value of the search term input box by default if one of the standard
+ * feeds is selected. This is to improve usability, as many of the standard
+ * feeds may not include results for even fairly popular search terms.
+ * @param {String} op The operation to perform.
+ * for querying all videos, or the name of one of the standard feeds.
+ * @param {Node} searchTermInputElement The HTML input element for the input
+ * element.
+ */
+ytVideoApp.queryTypeChanged = function(op, searchTermInputElement) {
+ if (op == 'search_username') {
+ searchTermInputElement.value = '-- enter username --';
+ } else if (op != 'search_all') {
+ searchTermInputElement.value = '';
+ }
+};
+
+/**
+ * Create a basic HTML form to use for creating a new playlist.
+ */
+ytVideoApp.prepareCreatePlaylistForm = function() {
+ var newPlaylistForm = ['<br /><form id="addPlaylist" ',
+ 'onsubmit="ytVideoApp.createNewPlaylist(this.newPlaylistTitle.value, ',
+ 'this.newPlaylistDescription.value); ">',
+ 'Enter a title for the new playlist:<br />',
+ '<input size="50" name="newPlaylistTitle" type="text" /><br />',
+ 'Enter a description:<br />',
+ '<textarea cols="25" name="newPlaylistDescription" >',
+ '</textarea><br />',
+ '<input type="submit" value="go">',
+ '</form>'].join('');
+
+ document.getElementById(ytVideoApp.PLAYLIST_ADD_DIV).innerHTML = newPlaylistForm;
+}
+
+/**
+* Uses ytVideoApp.sendRequest to create a new playlist.
+*
+* @param {String} playlistTitle The title of the new playlist
+* @param {String} playlistDescription A description of the new playlist
+*/
+ytVideoApp.createNewPlaylist = function(playlistTitle, playlistDescription) {
+ var filePath = 'operations.php';
+ var params = 'operation=create_playlist' +
+ '&playlistTitle=' + playlistTitle +
+ '&playlistDescription=' + playlistDescription;
+ ytVideoApp.hideNavigation();
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_SEARCH_RESULTS_DIV);
+}
+
+/**
+ * Confirm user wants to delete a playlist
+ *
+ * @param {String} playlistTitle The title of the playlist to be deleted
+ */
+ytVideoApp.confirmPlaylistDeletion = function(playlistTitle) {
+ var answer = confirm('Do you really want to delete the playlist titled : ' +
+ playlistTitle + ' ?');
+ if (answer) {
+ ytVideoApp.deletePlaylist(playlistTitle);
+ }
+}
+
+/**
+* Uses ytVideoApp.sendRequest to delete a playlist.
+*
+* @param {String} playlistTitle The title of the new playlist
+*/
+ytVideoApp.deletePlaylist = function(playlistTitle) {
+ var filePath = 'operations.php';
+ var params = 'operation=delete_playlist' +
+ '&playlistTitle=' + playlistTitle;
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_SEARCH_RESULTS_DIV);
+}
+
+/**
+ * Create a basic HTML form to use for modifying a playlist.
+ *
+ * @param {String} oldPlaylistTitle The old title of the playlist
+ * @param {String} oldPlaylistDescription The old description of the playlist
+ */
+ytVideoApp.prepareUpdatePlaylistForm = function(oldPlaylistTitle, oldPlaylistDescription) {
+ var playlistUpdateForm = ['<br /><form id="updatePlaylist" ',
+ 'onsubmit="ytVideoApp.updatePlaylist(this.newPlaylistTitle.value, ',
+ 'this.newPlaylistDescription.value, this.oldPlaylistTitle.value);">',
+ 'Enter a title for the new playlist:<br />',
+ '<input size="50" name="newPlaylistTitle" type="text" value="',
+ oldPlaylistTitle,
+ '"/><br />',
+ 'Enter a description:<br />',
+ '<textarea cols="25" name="newPlaylistDescription" >',
+ oldPlaylistDescription,
+ '</textarea><br />',
+ '<input type="submit" value="go" />',
+ '<input type="hidden" value="',
+ oldPlaylistTitle,
+ '" name="oldPlaylistTitle" />',
+ '</form>'].join('');
+
+ document.getElementById(ytVideoApp.VIDEO_SEARCH_RESULTS_DIV).innerHTML = playlistUpdateForm;
+}
+
+/**
+* Uses ytVideoApp.sendRequest to update a playlist.
+*
+* @param {String} newPlaylistTitle The new title of the playlist
+* @param {String} newPlaylistDescription A new description of the playlist
+*/
+ytVideoApp.updatePlaylist = function(newPlaylistTitle, newPlaylistDescription, oldPlaylistTitle) {
+ var filePath = 'operations.php';
+ var params = 'operation=update_playlist' +
+ '&newPlaylistTitle=' + newPlaylistTitle +
+ '&newPlaylistDescription=' + newPlaylistDescription +
+ '&oldPlaylistTitle=' + oldPlaylistTitle;
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_LIST_CONTAINER_DIV);
+}
+
+/**
+* Uses ytVideoApp.sendRequest to retrieve a users playlist.
+*
+*/
+ytVideoApp.retrievePlaylists = function() {
+ var filePath = 'operations.php';
+ var params = 'operation=retrieve_playlists';
+ ytVideoApp.hideNavigation();
+ ytVideoApp.sendRequest(filePath, params, ytVideoApp.VIDEO_LIST_CONTAINER_DIV);
+}