From 06f945f27840b53e57795dadbc38e76f7e11ab1c Mon Sep 17 00:00:00 2001 From: Horus3 Date: Mon, 24 Feb 2014 16:42:14 +0100 Subject: init --- .../Zend/Gdata/3LeggedOAuth/Gdata_OAuth_Helper.php | 109 ++ zend/demos/Zend/Gdata/3LeggedOAuth/data-api-72.png | Bin 0 -> 5294 bytes zend/demos/Zend/Gdata/3LeggedOAuth/doclist-72.png | Bin 0 -> 5696 bytes zend/demos/Zend/Gdata/3LeggedOAuth/index.php | 190 ++ zend/demos/Zend/Gdata/3LeggedOAuth/style.css | 43 + zend/demos/Zend/Gdata/Blogger.php | 373 ++++ .../Zend/Gdata/BooksBrowser/books_browser.css | 136 ++ zend/demos/Zend/Gdata/BooksBrowser/index.php | 155 ++ zend/demos/Zend/Gdata/BooksBrowser/interface.html | 81 + zend/demos/Zend/Gdata/Calendar.php | 841 +++++++++ zend/demos/Zend/Gdata/Docs.php | 940 +++++++++ zend/demos/Zend/Gdata/Gapps.php | 1992 ++++++++++++++++++++ zend/demos/Zend/Gdata/InstallationChecker.php | 386 ++++ zend/demos/Zend/Gdata/MyLibrary/demo.php | 226 +++ zend/demos/Zend/Gdata/Photos.php | 904 +++++++++ zend/demos/Zend/Gdata/Spreadsheet-ClientLogin.php | 454 +++++ zend/demos/Zend/Gdata/YouTubeVideoApp/README.txt | 44 + zend/demos/Zend/Gdata/YouTubeVideoApp/index.php | 193 ++ zend/demos/Zend/Gdata/YouTubeVideoApp/notfound.jpg | Bin 0 -> 1345 bytes .../Zend/Gdata/YouTubeVideoApp/operations.php | 1097 +++++++++++ .../Zend/Gdata/YouTubeVideoApp/session_details.php | 66 + .../demos/Zend/Gdata/YouTubeVideoApp/video_app.css | 236 +++ zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.js | 582 ++++++ .../demos/Zend/Gdata/YouTubeVideoBrowser/index.php | 278 +++ .../Zend/Gdata/YouTubeVideoBrowser/interface.html | 79 + .../Gdata/YouTubeVideoBrowser/video_browser.css | 152 ++ .../Gdata/YouTubeVideoBrowser/video_browser.js | 228 +++ 27 files changed, 9785 insertions(+) create mode 100755 zend/demos/Zend/Gdata/3LeggedOAuth/Gdata_OAuth_Helper.php create mode 100755 zend/demos/Zend/Gdata/3LeggedOAuth/data-api-72.png create mode 100755 zend/demos/Zend/Gdata/3LeggedOAuth/doclist-72.png create mode 100755 zend/demos/Zend/Gdata/3LeggedOAuth/index.php create mode 100755 zend/demos/Zend/Gdata/3LeggedOAuth/style.css create mode 100644 zend/demos/Zend/Gdata/Blogger.php create mode 100755 zend/demos/Zend/Gdata/BooksBrowser/books_browser.css create mode 100755 zend/demos/Zend/Gdata/BooksBrowser/index.php create mode 100644 zend/demos/Zend/Gdata/BooksBrowser/interface.html create mode 100644 zend/demos/Zend/Gdata/Calendar.php create mode 100755 zend/demos/Zend/Gdata/Docs.php create mode 100644 zend/demos/Zend/Gdata/Gapps.php create mode 100644 zend/demos/Zend/Gdata/InstallationChecker.php create mode 100755 zend/demos/Zend/Gdata/MyLibrary/demo.php create mode 100755 zend/demos/Zend/Gdata/Photos.php create mode 100644 zend/demos/Zend/Gdata/Spreadsheet-ClientLogin.php create mode 100644 zend/demos/Zend/Gdata/YouTubeVideoApp/README.txt create mode 100755 zend/demos/Zend/Gdata/YouTubeVideoApp/index.php create mode 100755 zend/demos/Zend/Gdata/YouTubeVideoApp/notfound.jpg create mode 100755 zend/demos/Zend/Gdata/YouTubeVideoApp/operations.php create mode 100755 zend/demos/Zend/Gdata/YouTubeVideoApp/session_details.php create mode 100755 zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.css create mode 100755 zend/demos/Zend/Gdata/YouTubeVideoApp/video_app.js create mode 100755 zend/demos/Zend/Gdata/YouTubeVideoBrowser/index.php create mode 100644 zend/demos/Zend/Gdata/YouTubeVideoBrowser/interface.html create mode 100644 zend/demos/Zend/Gdata/YouTubeVideoBrowser/video_browser.css create mode 100644 zend/demos/Zend/Gdata/YouTubeVideoBrowser/video_browser.js (limited to 'zend/demos') diff --git a/zend/demos/Zend/Gdata/3LeggedOAuth/Gdata_OAuth_Helper.php b/zend/demos/Zend/Gdata/3LeggedOAuth/Gdata_OAuth_Helper.php new file mode 100755 index 0000000..f0edd57 --- /dev/null +++ b/zend/demos/Zend/Gdata/3LeggedOAuth/Gdata_OAuth_Helper.php @@ -0,0 +1,109 @@ + Zend_Oauth::REQUEST_SCHEME_HEADER, + 'version' => '1.0', + 'requestTokenUrl' => 'https://www.google.com/accounts/OAuthGetRequestToken', + 'userAuthorizationUrl' => 'https://www.google.com/accounts/OAuthAuthorizeToken', + 'accessTokenUrl' => 'https://www.google.com/accounts/OAuthGetAccessToken' + ); + + /** + * Create Gdata_OAuth_Helper object + * + * @param string $consumerKey OAuth consumer key (domain). + * @param string $consumerSecret (optional) OAuth consumer secret. Required if + * using HMAC-SHA1 for a signature method. + * @param string $sigMethod (optional) The oauth_signature method to use. + * Defaults to HMAC-SHA1. RSA-SHA1 is also supported. + */ + public function __construct($consumerKey, $consumerSecret=null, + $sigMethod='HMAC-SHA1') { + $this->_defaultOptions['consumerKey'] = $consumerKey; + $this->_defaultOptions['consumerSecret'] = $consumerSecret; + $this->_defaultOptions['signatureMethod'] = $sigMethod; + parent::__construct($this->_defaultOptions); + } + + /** + * Getter for the oauth options array. + * + * @return array + */ + public function getOauthOptions() { + return $this->_defaultOptions; + } + + /** + * Fetches a request token. + * + * @param string $scope The API scope or scopes separated by spaces to + * restrict data access to. + * @param mixed $callback The URL to redirect the user to after they have + * granted access on the approval page. Either a string or + * Zend_Gdata_Query object. + * @return Zend_OAuth_Token_Request|null + */ + public function fetchRequestToken($scope, $callback) { + if ($callback instanceof Zend_Gdata_Query) { + $uri = $callback->getQueryUrl(); + } else { + $uri = $callback; + } + + $this->_defaultOptions['callbackUrl'] = $uri; + $this->_config->setCallbackUrl($uri); + if (!isset($_SESSION['ACCESS_TOKEN'])) { + return parent::getRequestToken(array('scope' => $scope)); + } + return null; + } + + /** + * Redirects the user to the approval page + * + * @param string $domain (optional) The Google Apps domain to logged users in + * under or 'default' for Google Accounts. Leaving this parameter off + * will give users the universal login to choose an account to login + * under. + * @return void + */ + public function authorizeRequestToken($domain=null) { + $params = array(); + if ($domain != null) { + $params = array('hd' => $domain); + } + $this->redirect($params); + } + + /** + * Upgrades an authorized request token to an access token. + * + * @return Zend_OAuth_Token_Access||null + */ + public function fetchAccessToken() { + if (!isset($_SESSION['ACCESS_TOKEN'])) { + if (!empty($_GET) && isset($_SESSION['REQUEST_TOKEN'])) { + return parent::getAccessToken( + $_GET, unserialize($_SESSION['REQUEST_TOKEN'])); + } + } + return null; + } +} diff --git a/zend/demos/Zend/Gdata/3LeggedOAuth/data-api-72.png b/zend/demos/Zend/Gdata/3LeggedOAuth/data-api-72.png new file mode 100755 index 0000000..e77c523 Binary files /dev/null and b/zend/demos/Zend/Gdata/3LeggedOAuth/data-api-72.png differ diff --git a/zend/demos/Zend/Gdata/3LeggedOAuth/doclist-72.png b/zend/demos/Zend/Gdata/3LeggedOAuth/doclist-72.png new file mode 100755 index 0000000..39de3a1 Binary files /dev/null and b/zend/demos/Zend/Gdata/3LeggedOAuth/doclist-72.png differ diff --git a/zend/demos/Zend/Gdata/3LeggedOAuth/index.php b/zend/demos/Zend/Gdata/3LeggedOAuth/index.php new file mode 100755 index 0000000..59aab08 --- /dev/null +++ b/zend/demos/Zend/Gdata/3LeggedOAuth/index.php @@ -0,0 +1,190 @@ +fetchRequestToken( + implode(' ', $scopes), $APP_URL . '?action=access_token')); + $consumer->authorizeRequestToken(); + break; + case 'access_token': + $_SESSION['ACCESS_TOKEN'] = serialize($consumer->fetchAccessToken()); + header('Location: ' . $APP_URL); + break; + default: + if (isset($_SESSION['ACCESS_TOKEN'])) { + $accessToken = unserialize($_SESSION['ACCESS_TOKEN']); + + $httpClient = $accessToken->getHttpClient( + $consumer->getOauthOptions()); + $docsService = new Zend_Gdata_Docs($httpClient, $APP_NAME); + $spreadsheetsService = new Zend_Gdata_Spreadsheets($httpClient, + $APP_NAME); + + // Retrieve user's list of Google Docs and spreadsheet list. + $docsFeed = $docsService->getDocumentListFeed(); + $spreadsheetFeed = $spreadsheetsService->getSpreadsheetFeed( + 'http://spreadsheets.google.com/feeds/spreadsheets/private/full?max-results=100'); + + renderHTML($accessToken, array($docsFeed, $spreadsheetFeed)); + } else { + renderHTML(); + } +} + +/** + * Returns a the base URL of the current running web app. + * + * @return string + */ +function getAppURL() { + $pageURL = 'http'; + if ($_SERVER['HTTPS'] == 'on') { + $pageURL .= 's'; + } + $pageURL .= '://'; + if ($_SERVER['SERVER_PORT'] != '80') { + $pageURL .= $_SERVER['SERVER_NAME'] . ':' . + $_SERVER['SERVER_PORT'] . $_SERVER['PHP_SELF']; + } else { + $pageURL .= $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF']; + } + return $pageURL; +} + +/** + * Removes session data and redirects the user to a URL. + * + * @param string $redirectUrl The URL to direct the user to after session data + * is destroyed. + * @return void + */ +function logout($redirectUrl) { + session_destroy(); + header('Location: ' . $redirectUrl); + exit; +} + +/** + * Prints the token string and secret of the token passed in. + * + * @param Zend_OAuth_Token $token An access or request token object to print. + * @return void + */ +function printToken($token) { + echo 'Token:' . $token->getToken() . '
'; + echo 'Token secret:' . $token->getTokenSecret() . '
'; +} + +/** + * Prints basic properties of a Google Data feed. + * + * @param Zend_Gdata_Feed $feed A feed object to print. + * @return void + */ +function printFeed($feed) { + echo '
    '; + foreach ($feed->entries as $entry) { + $alternateLink = ''; + foreach ($entry->link as $link) { + if ($link->getRel() == 'alternate') { + $alternateLink = $link->getHref(); + } + } + echo "
  1. $entry->title
  2. "; + } + echo '
'; +} + +/** + * Renders the page's HTML. + * + * @param Zend_OAuth_Token $token (optional) The user's current OAuth token. + * @param array $feeds (optional) An array of Zend_Gdata_Feed to print + * information for. + * @return void + */ +function renderHTML($token=null, $feeds=null) { +?> + + + + + + + + + + +
+ +
+
+
">Logout
+
+
+

First 100 documents from the Documents List Data API:

+
+
+
+

First 100 spreadsheets from the Spreadsheets Data API:

+
+
+
+ + + +gdClient = new Zend_Gdata($client); + } + + /** + * This function retrieves all the blogs associated with the authenticated + * user and prompts the user to choose which to manipulate. + * + * Once the index is selected by the user, the corresponding blogID is + * extracted and stored for easy access. + * + * @return void + */ + public function promptForBlogID() + { + $query = new Zend_Gdata_Query('http://www.blogger.com/feeds/default/blogs'); + $feed = $this->gdClient->getFeed($query); + $this->printFeed($feed); + $input = getInput("\nSelection"); + + //id text is of the form: tag:blogger.com,1999:user-blogID.blogs + $idText = explode('-', $feed->entries[$input]->id->text); + $this->blogID = $idText[2]; + } + + /** + * This function creates a new Zend_Gdata_Entry representing a blog + * post, and inserts it into the user's blog. It also checks for + * whether the post should be added as a draft or as a published + * post. + * + * @param string $title The title of the blog post. + * @param string $content The body of the post. + * @param boolean $isDraft Whether the post should be added as a draft or as a published post + * @return string The newly created post's ID + */ + public function createPost($title, $content, $isDraft=False) + { + // We're using the magic factory method to create a Zend_Gdata_Entry. + // http://framework.zend.com/manual/en/zend.gdata.html#zend.gdata.introdduction.magicfactory + $entry = $this->gdClient->newEntry(); + + $entry->title = $this->gdClient->newTitle(trim($title)); + $entry->content = $this->gdClient->newContent(trim($content)); + $entry->content->setType('text'); + $uri = "http://www.blogger.com/feeds/" . $this->blogID . "/posts/default"; + + if ($isDraft) + { + $control = $this->gdClient->newControl(); + $draft = $this->gdClient->newDraft('yes'); + $control->setDraft($draft); + $entry->control = $control; + } + + $createdPost = $this->gdClient->insertEntry($entry, $uri); + //format of id text: tag:blogger.com,1999:blog-blogID.post-postID + $idText = explode('-', $createdPost->id->text); + $postID = $idText[2]; + + return $postID; + } + + /** + * Prints the titles of all the posts in the user's blog. + * + * @return void + */ + public function printAllPosts() + { + $query = new Zend_Gdata_Query('http://www.blogger.com/feeds/' . $this->blogID . '/posts/default'); + $feed = $this->gdClient->getFeed($query); + $this->printFeed($feed); + } + + /** + * Retrieves the specified post and updates the title and body. Also sets + * the post's draft status. + * + * @param string $postID The ID of the post to update. PostID in field: + * tag:blogger.com,1999:blog-blogID.post-postID + * @param string $updatedTitle The new title of the post. + * @param string $updatedContent The new body of the post. + * @param boolean $isDraft Whether the post will be published or saved as a draft. + * @return Zend_Gdata_Entry The updated post. + */ + public function updatePost($postID, $updatedTitle, $updatedContent, $isDraft) + { + $query = new Zend_Gdata_Query('http://www.blogger.com/feeds/' . $this->blogID . '/posts/default/' . $postID); + $postToUpdate = $this->gdClient->getEntry($query); + $postToUpdate->title->text = $this->gdClient->newTitle(trim($updatedTitle)); + $postToUpdate->content->text = $this->gdClient->newContent(trim($updatedContent)); + + if ($isDraft) { + $draft = $this->gdClient->newDraft('yes'); + } else { + $draft = $this->gdClient->newDraft('no'); + } + + $control = $this->gdClient->newControl(); + $control->setDraft($draft); + $postToUpdate->control = $control; + $updatedPost = $postToUpdate->save(); + + return $updatedPost; + } + + /** + * This function uses query parameters to retrieve and print all posts + * within a specified date range. + * + * @param string $startDate Beginning date, inclusive. Preferred format is a RFC-3339 date, + * though other formats are accepted. + * @param string $endDate End date, exclusive. + * @return void + */ + public function printPostsInDateRange($startDate, $endDate) + { + $query = new Zend_Gdata_Query('http://www.blogger.com/feeds/' . $this->blogID . '/posts/default'); + $query->setParam('published-min', $startDate); + $query->setParam('published-max', $endDate); + + $feed = $this->gdClient->getFeed($query); + $this->printFeed($feed); + } + + /** + * This function creates a new comment and adds it to the specified post. + * A comment is created as a Zend_Gdata_Entry. + * + * @param string $postID The ID of the post to add the comment to. PostID + * in the field: tag:blogger.com,1999:blog-blogID.post-postID + * @param string $commentText The text of the comment to add. + * @return string The ID of the newly created comment. + */ + public function createComment($postID, $commentText) + { + $uri = 'http://www.blogger.com/feeds/' . $this->blogID . '/' . $postID . '/comments/default'; + + $newComment = $this->gdClient->newEntry(); + $newComment->content = $this->gdClient->newContent($commentText); + $newComment->content->setType('text'); + $createdComment = $this->gdClient->insertEntry($newComment, $uri); + + echo 'Added new comment: ' . $createdComment->content->text . "\n"; + // Edit link follows format: /feeds/blogID/postID/comments/default/commentID + $editLink = explode('/', $createdComment->getEditLink()->href); + $commentID = $editLink[8]; + + return $commentID; + } + + /** + * This function prints all comments associated with the specified post. + * + * @param string $postID The ID of the post whose comments we'll print. + * @return void + */ + public function printAllComments($postID) + { + $query = new Zend_Gdata_Query('http://www.blogger.com/feeds/' . $this->blogID . '/' . $postID . '/comments/default'); + $feed = $this->gdClient->getFeed($query); + $this->printFeed($feed); + } + + /** + * This function deletes the specified comment from a post. + * + * @param string $postID The ID of the post where the comment is. PostID in + * the field: tag:blogger.com,1999:blog-blogID.post-postID + * @param string $commentID The ID of the comment to delete. The commentID + * in the editURL: /feeds/blogID/postID/comments/default/commentID + * @return void + */ + public function deleteComment($postID, $commentID) + { + $uri = 'http://www.blogger.com/feeds/' . $this->blogID . '/' . $postID . '/comments/default/' . $commentID; + $this->gdClient->delete($uri); + } + + /** + * This function deletes the specified post. + * + * @param string $postID The ID of the post to delete. + * @return void + */ + public function deletePost($postID) + { + $uri = 'http://www.blogger.com/feeds/' . $this->blogID . '/posts/default/' . $postID; + $this->gdClient->delete($uri); + } + + /** + * Helper function to print out the titles of all supplied Blogger + * feeds. + * + * @param Zend_Gdata_Feed The feed to print. + * @return void + */ + public function printFeed($feed) + { + $i = 0; + foreach($feed->entries as $entry) + { + echo "\t" . $i ." ". $entry->title->text . "\n"; + $i++; + } + } + + /** + * Runs the sample. + * + * @return void + */ + public function run() + { + echo "Note: This sample may Create, Read, Update and Delete data " . + "stored in the account provided. Please exit now if you provided " . + "an account which contains important data.\n\n"; + $this->promptForBlogID(); + + echo "Creating a post.\n"; + $this->createPost('Hello, world!', 'I am on the intarweb!', False); + + echo "Creating a draft post.\n"; + $postID = $this->createPost('Salutations, world!', 'Does not sound right.. must work on title.', True); + + echo "Updating the previous post and publishing it.\n"; + $updatedPost = $this->updatePost($postID, 'Hello, world, it is.', 'There we go.', False); + echo "The new title of the post is: " . $updatedPost->title->text . "\n"; + echo "The new body of the post is: " . $updatedPost->content->text . "\n"; + + echo "Adding a comment to the previous post.\n"; + $this->createComment($postID, 'I am so glad this is public now.'); + + echo "Adding another comment.\n"; + $commentID = $this->createComment($postID, 'This is a spammy comment.'); + + echo "Deleting the previous comment.\n"; + $this->deleteComment($postID, $commentID); + + echo "Printing all posts.\n"; + $this->printAllPosts(); + + echo "Printing posts between 2007-01-01 and 2007-03-01.\n"; + $this->printPostsInDateRange('2007-01-01','2007-06-30'); + + echo "Deleting the post titled: " . $updatedPost->title->text . "\n"; + $this->deletePost($postID); + } +} + +/** + * Gets credentials from user. + * + * @param string $text + * @return string Index of the blog the user has chosen. + */ +function getInput($text) +{ + echo $text.': '; + return trim(fgets(STDIN)); +} + +$user = null; +$pass = null; + +// process command line options +foreach ($argv as $argument) { + $argParts = explode('=', $argument); + if ($argParts[0] == '--user') { + $user = $argParts[1]; + } else if ($argParts[0] == '--pass') { + $pass = $argParts[1]; + } +} + +if (($user == null) || ($pass == null)) { + exit("php Blogger.php --user=[username] --pass=[password]\n"); +} + +$sample = new SimpleCRUD($user, $pass); +$sample->run(); diff --git a/zend/demos/Zend/Gdata/BooksBrowser/books_browser.css b/zend/demos/Zend/Gdata/BooksBrowser/books_browser.css new file mode 100755 index 0000000..6ad2bbe --- /dev/null +++ b/zend/demos/Zend/Gdata/BooksBrowser/books_browser.css @@ -0,0 +1,136 @@ +body { + background-color: white; + color: black; + font-family: Arial, sans-serif; + font-size: small; + margin: 8px; + margin-top: 3px; +} + +.thumbnail img { + border-color:black; + border-width:1; + border-style:solid; +} + +table { + border-collapse: collapse; +} + +th, td { + padding: 0; + vertical-align: top; + text-align: left; + font-size: small; +} + +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; +} + +form { + display: inline; + margin: 0; + padding: 0; +} + +.volumeList td { + padding-bottom: 5px; + padding-right: 5px; +} + +#titleBar { + border: 1px solid silver; + background-color: #e5ecf9; + font-size: large; + font-weight: bold; + 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; +} + +#mainSearchBox { + background-color: #e5ecf9; + border: 1px solid silver; + width: 300; + padding-top: 5px; + padding-bottom: 10px; + padding-left: 10px; + padding-right: 10px; +} + +#searchResults { + width: 100%; +} + +.volumeList td +{ + border-top: 1px solid #aaaaaa; + padding: 6px; +} + +.thumbnail +{ + height: 80px; + padding: 3px; +} + +.previewbutton +{ + border: 0px; + margin: 6px 0px 6px 0px; +} + +#resultcell +{ + padding-right: 20px; +} + +#previewcell +{ + border-left: 1px dotted #aaa; + padding-left: 20px; + display: none; + padding-right: 20px; +} + +#viewport { + height: 500px; + width: 100%; + border: 1px solid #aaa; + +} + +/* Google Preview: Boilerplate styling */ +#viewport { font-size: 16px; line-height: 1; } +#viewport img, #viewport table, #viewport div, #viewport td +{ border: 0; padding: 0; margin: 0; background: none } +#viewport td { vertical-align: middle } + diff --git a/zend/demos/Zend/Gdata/BooksBrowser/index.php b/zend/demos/Zend/Gdata/BooksBrowser/index.php new file mode 100755 index 0000000..8d5e9ad --- /dev/null +++ b/zend/demos/Zend/Gdata/BooksBrowser/index.php @@ -0,0 +1,155 @@ + +
+ +HTML; + $flipflop = false; + foreach ($feed as $entry) { + $title = printArray($entry->getTitles()); + $volumeId = $entry->getVolumeId(); + if ($thumbnailLink = $entry->getThumbnailLink()) { + $thumbnail = $thumbnailLink->href; + } else { + $thumbnail = null; + } + $preview = $entry->getPreviewLink()->href; + $embeddability = $entry->getEmbeddability()->getValue(); + $creators = printArray($entry->getCreators()); + if (!empty($creators)) $creators = "by " . $creators; + if ($embeddability == + "http://schemas.google.com/books/2008#embeddable") { + $preview_link = ''. + '' . + '
'; + } else { + $preview_link = ''; + } + $thumbnail_img = (!$thumbnail) ? '' : ''; + + print << + + +HTML; + } + print << +
+ $thumbnail_img +
+ $title
+ $creators
+ $preview_link +
  +

+HTML; +} + +/* + * The main controller logic of the Books volume browser demonstration app. + */ +$queryType = isset($_GET['queryType']) ? $_GET['queryType'] : null; + +include 'interface.html'; + +if ($queryType === null) { + /* display the entire interface */ +} else { + $books = new Zend_Gdata_Books(); + $query = $books->newVolumeQuery(); + + /* display a list of volumes */ + if (isset($_GET['searchTerm'])) { + $searchTerm = $_GET['searchTerm']; + $query->setQuery($searchTerm); + } + if (isset($_GET['startIndex'])) { + $startIndex = $_GET['startIndex']; + $query->setStartIndex($startIndex); + } + if (isset($_GET['maxResults'])) { + $maxResults = $_GET['maxResults']; + $query->setMaxResults($maxResults); + } + if (isset($_GET['minViewability'])) { + $minViewability = $_GET['minViewability']; + $query->setMinViewability($minViewability); + } + + /* check for one of the restricted feeds, or list from 'all' videos */ + switch ($queryType) { + case 'full_view': + case 'partial_view': + $query->setMinViewability($queryType); + echo 'Requesting feed: ' . ($query->getQueryUrl()) . '

'; + $feed = $books->getVolumeFeed($query); + break; + case 'all': + echo 'Requesting feed: ' . ($query->getQueryUrl()) . '

'; + $feed = $books->getVolumeFeed($query); + break; + default: + echo 'ERROR - unknown queryType - "' . $queryType . '"'; + break; + } + echoBookList($feed); +} + diff --git a/zend/demos/Zend/Gdata/BooksBrowser/interface.html b/zend/demos/Zend/Gdata/BooksBrowser/interface.html new file mode 100644 index 0000000..55530c9 --- /dev/null +++ b/zend/demos/Zend/Gdata/BooksBrowser/interface.html @@ -0,0 +1,81 @@ + + + + Books Data API Browser in PHP + + + + + + + +
+

Books Data API Browser in PHP

+
+
+
+
+

Search Books:

+
+ + + + + +
+
+
+
+ + diff --git a/zend/demos/Zend/Gdata/Calendar.php b/zend/demos/Zend/Gdata/Calendar.php new file mode 100644 index 0000000..1094343 --- /dev/null +++ b/zend/demos/Zend/Gdata/Calendar.php @@ -0,0 +1,841 @@ += 5.2.11 + * + * You can run this sample both from the command line (CLI) and also + * from a web browser. When running through a web browser, only + * AuthSub and outputting a list of calendars is demonstrated. When + * running via CLI, all functionality except AuthSub is available and dependent + * upon the command line options passed. Run this script without any + * command line options to see usage, eg: + * /usr/local/bin/php -f Calendar.php + * + * More information on the Command Line Interface is available at: + * http://www.php.net/features.commandline + * + * NOTE: You must ensure that the Zend Framework is in your PHP include + * path. You can do this via php.ini settings, or by modifying the + * argument to set_include_path in the code below. + * + * NOTE: As this is sample code, not all of the functions do full error + * handling. Please see getEvent for an example of how errors could + * be handled and the online code samples for additional information. + */ + +/** + * @see Zend_Loader + */ +require_once 'Zend/Loader.php'; + +/** + * @see Zend_Gdata + */ +Zend_Loader::loadClass('Zend_Gdata'); + +/** + * @see Zend_Gdata_AuthSub + */ +Zend_Loader::loadClass('Zend_Gdata_AuthSub'); + +/** + * @see Zend_Gdata_ClientLogin + */ +Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); + +/** + * @see Zend_Gdata_HttpClient + */ +Zend_Loader::loadClass('Zend_Gdata_HttpClient'); + +/** + * @see Zend_Gdata_Calendar + */ +Zend_Loader::loadClass('Zend_Gdata_Calendar'); + +/** + * @var string Location of AuthSub key file. include_path is used to find this + */ +$_authSubKeyFile = null; // Example value for secure use: 'mykey.pem' + +/** + * @var string Passphrase for AuthSub key file. + */ +$_authSubKeyFilePassphrase = null; + +/** + * Returns the full URL of the current page, based upon env variables + * + * Env variables used: + * $_SERVER['HTTPS'] = (on|off|) + * $_SERVER['HTTP_HOST'] = value of the Host: header + * $_SERVER['SERVER_PORT'] = port number (only used if not http/80,https/443) + * $_SERVER['REQUEST_URI'] = the URI after the method of the HTTP request + * + * @return string Current URL + */ +function getCurrentUrl() +{ + global $_SERVER; + + /** + * Filter php_self to avoid a security vulnerability. + */ + $php_request_uri = 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 . $php_request_uri; +} + +/** + * Returns the AuthSub URL which the user must visit to authenticate requests + * from this application. + * + * Uses getCurrentUrl() to get the next URL which the user will be redirected + * to after successfully authenticating with the Google service. + * + * @return string AuthSub URL + */ +function getAuthSubUrl() +{ + global $_authSubKeyFile; + $next = getCurrentUrl(); + $scope = 'http://www.google.com/calendar/feeds/'; + $session = true; + if ($_authSubKeyFile != null) { + $secure = true; + } else { + $secure = false; + } + return Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, + $session); +} + +/** + * Outputs a request to the user to login to their Google account, including + * a link to the AuthSub URL. + * + * Uses getAuthSubUrl() to get the URL which the user must visit to authenticate + * + * @return void + */ +function requestUserLogin($linkText) +{ + $authSubUrl = getAuthSubUrl(); + echo "{$linkText}"; +} + +/** + * Returns a HTTP client object with the appropriate headers for communicating + * with Google using AuthSub authentication. + * + * Uses the $_SESSION['sessionToken'] to store the AuthSub session token after + * it is obtained. The single use token supplied in the URL when redirected + * after the user succesfully authenticated to Google is retrieved from the + * $_GET['token'] variable. + * + * @return Zend_Http_Client + */ +function getAuthSubHttpClient() +{ + global $_SESSION, $_GET, $_authSubKeyFile, $_authSubKeyFilePassphrase; + $client = new Zend_Gdata_HttpClient(); + if ($_authSubKeyFile != null) { + // set the AuthSub key + $client->setAuthSubPrivateKeyFile($_authSubKeyFile, $_authSubKeyFilePassphrase, true); + } + if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) { + $_SESSION['sessionToken'] = + Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token'], $client); + } + $client->setAuthSubToken($_SESSION['sessionToken']); + return $client; +} + +/** + * Processes loading of this sample code through a web browser. Uses AuthSub + * authentication and outputs a list of a user's calendars if succesfully + * authenticated. + * + * @return void + */ +function processPageLoad() +{ + global $_SESSION, $_GET; + if (!isset($_SESSION['sessionToken']) && !isset($_GET['token'])) { + requestUserLogin('Please login to your Google Account.'); + } else { + $client = getAuthSubHttpClient(); + outputCalendarList($client); + } +} + +/** + * Returns a HTTP client object with the appropriate headers for communicating + * with Google using the ClientLogin credentials supplied. + * + * @param string $user The username, in e-mail address format, to authenticate + * @param string $pass The password for the user specified + * @return Zend_Http_Client + */ +function getClientLoginHttpClient($user, $pass) +{ + $service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME; + + $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); + return $client; +} + +/** + * Outputs an HTML unordered list (ul), with each list item representing an event + * in the user's calendar. The calendar is retrieved using the magic cookie + * which allows read-only access to private calendar data using a special token + * available from within the Calendar UI. + * + * @param string $user The username or address of the calendar to be retrieved. + * @param string $magicCookie The magic cookie token + * @return void + */ +function outputCalendarMagicCookie($user, $magicCookie) +{ + $gdataCal = new Zend_Gdata_Calendar(); + $query = $gdataCal->newEventQuery(); + $query->setUser($user); + $query->setVisibility('private-' . $magicCookie); + $query->setProjection('full'); + $eventFeed = $gdataCal->getCalendarEventFeed($query); + echo "
    \n"; + foreach ($eventFeed as $event) { + echo "\t
  • " . $event->title->text . "
  • \n"; + $sl = $event->getLink('self')->href; + } + echo "
\n"; +} + +/** + * Outputs an HTML unordered list (ul), with each list item representing a + * calendar in the authenticated user's calendar list. + * + * @param Zend_Http_Client $client The authenticated client object + * @return void + */ +function outputCalendarList($client) +{ + $gdataCal = new Zend_Gdata_Calendar($client); + $calFeed = $gdataCal->getCalendarListFeed(); + echo "

" . $calFeed->title->text . "

\n"; + echo "
    \n"; + foreach ($calFeed as $calendar) { + echo "\t
  • " . $calendar->title->text . "
  • \n"; + } + echo "
\n"; +} + +/** + * Outputs an HTML unordered list (ul), with each list item representing an + * event on the authenticated user's calendar. Includes the start time and + * event ID in the output. Events are ordered by starttime and include only + * events occurring in the future. + * + * @param Zend_Http_Client $client The authenticated client object + * @return void + */ +function outputCalendar($client) +{ + $gdataCal = new Zend_Gdata_Calendar($client); + $query = $gdataCal->newEventQuery(); + $query->setUser('default'); + $query->setVisibility('private'); + $query->setProjection('full'); + $query->setOrderby('starttime'); + $query->setFutureevents(true); + $eventFeed = $gdataCal->getCalendarEventFeed($query); + // option 2 + // $eventFeed = $gdataCal->getCalendarEventFeed($query->getQueryUrl()); + echo "
    \n"; + foreach ($eventFeed as $event) { + echo "\t
  • " . $event->title->text . " (" . $event->id->text . ")\n"; + // Zend_Gdata_App_Extensions_Title->__toString() is defined, so the + // following will also work on PHP >= 5.2.0 + //echo "\t
  • " . $event->title . " (" . $event->id . ")\n"; + echo "\t\t
      \n"; + foreach ($event->when as $when) { + echo "\t\t\t
    • Starts: " . $when->startTime . "
    • \n"; + } + echo "\t\t
    \n"; + echo "\t
  • \n"; + } + echo "
\n"; +} + +/** + * Outputs an HTML unordered list (ul), with each list item representing an + * event on the authenticated user's calendar which occurs during the + * specified date range. + * + * To query for all events occurring on 2006-12-24, you would query for + * a startDate of '2006-12-24' and an endDate of '2006-12-25' as the upper + * bound for date queries is exclusive. See the 'query parameters reference': + * http://code.google.com/apis/gdata/calendar.html#Parameters + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $startDate The start date in YYYY-MM-DD format + * @param string $endDate The end date in YYYY-MM-DD format + * @return void + */ +function outputCalendarByDateRange($client, $startDate='2007-05-01', + $endDate='2007-08-01') +{ + $gdataCal = new Zend_Gdata_Calendar($client); + $query = $gdataCal->newEventQuery(); + $query->setUser('default'); + $query->setVisibility('private'); + $query->setProjection('full'); + $query->setOrderby('starttime'); + $query->setStartMin($startDate); + $query->setStartMax($endDate); + $eventFeed = $gdataCal->getCalendarEventFeed($query); + echo "
    \n"; + foreach ($eventFeed as $event) { + echo "\t
  • " . $event->title->text . " (" . $event->id->text . ")\n"; + echo "\t\t
      \n"; + foreach ($event->when as $when) { + echo "\t\t\t
    • Starts: " . $when->startTime . "
    • \n"; + } + echo "\t\t
    \n"; + echo "\t
  • \n"; + } + echo "
\n"; +} + +/** + * Outputs an HTML unordered list (ul), with each list item representing an + * event on the authenticated user's calendar which matches the search string + * specified as the $fullTextQuery parameter + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $fullTextQuery The string for which you are searching + * @return void + */ +function outputCalendarByFullTextQuery($client, $fullTextQuery='tennis') +{ + $gdataCal = new Zend_Gdata_Calendar($client); + $query = $gdataCal->newEventQuery(); + $query->setUser('default'); + $query->setVisibility('private'); + $query->setProjection('full'); + $query->setQuery($fullTextQuery); + $eventFeed = $gdataCal->getCalendarEventFeed($query); + echo "
    \n"; + foreach ($eventFeed as $event) { + echo "\t
  • " . $event->title->text . " (" . $event->id->text . ")\n"; + echo "\t\t
      \n"; + foreach ($event->when as $when) { + echo "\t\t\t
    • Starts: " . $when->startTime . "
    • \n"; + echo "\t\t
    \n"; + echo "\t
  • \n"; + } + } + echo "
\n"; +} + +/** + * Creates an event on the authenticated user's default calendar with the + * specified event details. + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $title The event title + * @param string $desc The detailed description of the event + * @param string $where + * @param string $startDate The start date of the event in YYYY-MM-DD format + * @param string $startTime The start time of the event in HH:MM 24hr format + * @param string $endDate The end date of the event in YYYY-MM-DD format + * @param string $endTime The end time of the event in HH:MM 24hr format + * @param string $tzOffset The offset from GMT/UTC in [+-]DD format (eg -08) + * @return string The ID URL for the event. + */ +function createEvent ($client, $title = 'Tennis with Beth', + $desc='Meet for a quick lesson', $where = 'On the courts', + $startDate = '2008-01-20', $startTime = '10:00', + $endDate = '2008-01-20', $endTime = '11:00', $tzOffset = '-08') +{ + $gc = new Zend_Gdata_Calendar($client); + $newEntry = $gc->newEventEntry(); + $newEntry->title = $gc->newTitle(trim($title)); + $newEntry->where = array($gc->newWhere($where)); + + $newEntry->content = $gc->newContent($desc); + $newEntry->content->type = 'text'; + + $when = $gc->newWhen(); + $when->startTime = "{$startDate}T{$startTime}:00.000{$tzOffset}:00"; + $when->endTime = "{$endDate}T{$endTime}:00.000{$tzOffset}:00"; + $newEntry->when = array($when); + + $createdEntry = $gc->insertEvent($newEntry); + return $createdEntry->id->text; +} + +/** + * Creates an event on the authenticated user's default calendar using + * the specified QuickAdd string. + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $quickAddText The QuickAdd text for the event + * @return string The ID URL for the event + */ +function createQuickAddEvent ($client, $quickAddText) { + $gdataCal = new Zend_Gdata_Calendar($client); + $event = $gdataCal->newEventEntry(); + $event->content = $gdataCal->newContent($quickAddText); + $event->quickAdd = $gdataCal->newQuickAdd(true); + + $newEvent = $gdataCal->insertEvent($event); + return $newEvent->id->text; +} + +/** + * Creates a new web content event on the authenticated user's default + * calendar with the specified event details. For simplicity, the event + * is created as an all day event and does not include a description. + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $title The event title + * @param string $startDate The start date of the event in YYYY-MM-DD format + * @param string $endDate The end time of the event in HH:MM 24hr format + * @param string $icon URL pointing to a 16x16 px icon representing the event. + * @param string $url The URL containing the web content for the event. + * @param string $height The desired height of the web content pane. + * @param string $width The desired width of the web content pane. + * @param string $type The MIME type of the web content. + * @return string The ID URL for the event. + */ +function createWebContentEvent ($client, $title = 'World Cup 2006', + $startDate = '2006-06-09', $endDate = '2006-06-09', + $icon = 'http://www.google.com/calendar/images/google-holiday.gif', + $url = 'http://www.google.com/logos/worldcup06.gif', + $height = '120', $width = '276', $type = 'image/gif' + ) +{ + $gc = new Zend_Gdata_Calendar($client); + $newEntry = $gc->newEventEntry(); + $newEntry->title = $gc->newTitle(trim($title)); + + $when = $gc->newWhen(); + $when->startTime = $startDate; + $when->endTime = $endDate; + $newEntry->when = array($when); + + $wc = $gc->newWebContent(); + $wc->url = $url; + $wc->height = $height; + $wc->width = $width; + + $wcLink = $gc->newLink(); + $wcLink->rel = "http://schemas.google.com/gCal/2005/webContent"; + $wcLink->title = $title; + $wcLink->type = $type; + $wcLink->href = $icon; + + $wcLink->webContent = $wc; + $newEntry->link = array($wcLink); + + $createdEntry = $gc->insertEvent($newEntry); + return $createdEntry->id->text; +} + +/** + * Creates a recurring event on the authenticated user's default calendar with + * the specified event details. + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $title The event title + * @param string $desc The detailed description of the event + * @param string $where + * @param string $recurData The iCalendar recurring event syntax (RFC2445) + * @return void + */ +function createRecurringEvent ($client, $title = 'Tennis with Beth', + $desc='Meet for a quick lesson', $where = 'On the courts', + $recurData = null) +{ + $gc = new Zend_Gdata_Calendar($client); + $newEntry = $gc->newEventEntry(); + $newEntry->title = $gc->newTitle(trim($title)); + $newEntry->where = array($gc->newWhere($where)); + + $newEntry->content = $gc->newContent($desc); + $newEntry->content->type = 'text'; + + /** + * Due to the length of this recurrence syntax, we did not specify + * it as a default parameter value directly + */ + if ($recurData == null) { + $recurData = + "DTSTART;VALUE=DATE:20070501\r\n" . + "DTEND;VALUE=DATE:20070502\r\n" . + "RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n"; + } + + $newEntry->recurrence = $gc->newRecurrence($recurData); + + $gc->post($newEntry->saveXML()); +} + +/** + * Returns an entry object representing the event with the specified ID. + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $eventId The event ID string + * @return Zend_Gdata_Calendar_EventEntry|null if the event is found, null if it's not + */ +function getEvent($client, $eventId) +{ + $gdataCal = new Zend_Gdata_Calendar($client); + $query = $gdataCal->newEventQuery(); + $query->setUser('default'); + $query->setVisibility('private'); + $query->setProjection('full'); + $query->setEvent($eventId); + + try { + $eventEntry = $gdataCal->getCalendarEventEntry($query); + return $eventEntry; + } catch (Zend_Gdata_App_Exception $e) { + var_dump($e); + return null; + } +} + +/** + * Updates the title of the event with the specified ID to be + * the title specified. Also outputs the new and old title + * with HTML br elements separating the lines + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $eventId The event ID string + * @param string $newTitle The new title to set on this event + * @return Zend_Gdata_Calendar_EventEntry|null The updated entry + */ +function updateEvent ($client, $eventId, $newTitle) +{ + $gdataCal = new Zend_Gdata_Calendar($client); + if ($eventOld = getEvent($client, $eventId)) { + echo "Old title: " . $eventOld->title->text . "
\n"; + $eventOld->title = $gdataCal->newTitle($newTitle); + try { + $eventOld->save(); + } catch (Zend_Gdata_App_Exception $e) { + var_dump($e); + return null; + } + $eventNew = getEvent($client, $eventId); + echo "New title: " . $eventNew->title->text . "
\n"; + return $eventNew; + } else { + return null; + } +} + +/** + * Adds an extended property to the event specified as a parameter. + * An extended property is an arbitrary name/value pair that can be added + * to an event and retrieved via the API. It is not accessible from the + * calendar web interface. + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $eventId The event ID string + * @param string $name The name of the extended property + * @param string $value The value of the extended property + * @return Zend_Gdata_Calendar_EventEntry|null The updated entry + */ +function addExtendedProperty ($client, $eventId, + $name='http://www.example.com/schemas/2005#mycal.id', $value='1234') +{ + $gc = new Zend_Gdata_Calendar($client); + if ($event = getEvent($client, $eventId)) { + $extProp = $gc->newExtendedProperty($name, $value); + $extProps = array_merge($event->extendedProperty, array($extProp)); + $event->extendedProperty = $extProps; + $eventNew = $event->save(); + return $eventNew; + } else { + return null; + } +} + + +/** + * Adds a reminder to the event specified as a parameter. + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $eventId The event ID string + * @param integer $minutes Minutes before event to set reminder + * @return Zend_Gdata_Calendar_EventEntry|null The updated entry + */ +function setReminder($client, $eventId, $minutes=15) +{ + $gc = new Zend_Gdata_Calendar($client); + $method = "alert"; + if ($event = getEvent($client, $eventId)) { + $times = $event->when; + foreach ($times as $when) { + $reminder = $gc->newReminder(); + $reminder->setMinutes($minutes); + $reminder->setMethod($method); + $when->reminders = array($reminder); + } + $eventNew = $event->save(); + return $eventNew; + } else { + return null; + } +} + +/** + * Deletes the event specified by retrieving the atom entry object + * and calling Zend_Feed_EntryAtom::delete() method. This is for + * example purposes only, as it is inefficient to retrieve the entire + * atom entry only for the purposes of deleting it. + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $eventId The event ID string + * @return void + */ +function deleteEventById ($client, $eventId) +{ + $event = getEvent($client, $eventId); + $event->delete(); +} + +/** + * Deletes the event specified by calling the Zend_Gdata::delete() + * method. The URL is typically in the format of: + * http://www.google.com/calendar/feeds/default/private/full/ + * + * @param Zend_Http_Client $client The authenticated client object + * @param string $url The url for the event to be deleted + * @return void + */ +function deleteEventByUrl ($client, $url) +{ + $gdataCal = new Zend_Gdata_Calendar($client); + $gdataCal->delete($url); +} + +/** + * Main logic for running this sample code via the command line or, + * for AuthSub functionality only, via a web browser. The output of + * many of the functions is in HTML format for demonstration purposes, + * so you may wish to pipe the output to Tidy when running from the + * command-line for clearer results. + * + * Run without any arguments to get usage information + */ +if (isset($argc) && $argc >= 2) { + switch ($argv[1]) { + case 'outputCalendar': + if ($argc == 4) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + outputCalendar($client); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n"; + } + break; + case 'outputCalendarMagicCookie': + if ($argc == 4) { + outputCalendarMagicCookie($argv[2], $argv[3]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n"; + } + break; + case 'outputCalendarByDateRange': + if ($argc == 6) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + outputCalendarByDateRange($client, $argv[4], $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n"; + } + break; + case 'outputCalendarByFullTextQuery': + if ($argc == 5) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + outputCalendarByFullTextQuery($client, $argv[4]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n"; + } + break; + case 'outputCalendarList': + if ($argc == 4) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + outputCalendarList($client); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n"; + } + break; + case 'updateEvent': + if ($argc == 6) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + updateEvent($client, $argv[4], $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n"; + } + break; + case 'setReminder': + if ($argc == 6) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + setReminder($client, $argv[4], $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n"; + } + break; + case 'addExtendedProperty': + if ($argc == 7) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + addExtendedProperty($client, $argv[4], $argv[5], $argv[6]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n"; + } + break; + case 'deleteEventById': + if ($argc == 5) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + deleteEventById($client, $argv[4]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n"; + } + break; + case 'deleteEventByUrl': + if ($argc == 5) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + deleteEventByUrl($client, $argv[4]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n"; + } + break; + case 'createEvent': + if ($argc == 12) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + $id = createEvent($client, $argv[4], $argv[5], $argv[6], $argv[7], + $argv[8], $argv[9], $argv[10], $argv[11]); + print "Event created with ID: $id\n"; + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " <description> <where> " . + "<startDate> <startTime> <endDate> <endTime> <tzOffset>\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} <username> <password> " . + "'Tennis with Beth' 'Meet for a quick lesson' 'On the courts' " . + "'2008-01-01' '10:00' '2008-01-01' '11:00' '-08'\n"; + } + break; + case 'createQuickAddEvent': + if ($argc == 5) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + $id = createQuickAddEvent($client, $argv[4]); + print "Event created with ID: $id\n"; + } else { + echo "Usage: php {$argv[0]} {$argv[1]} <username> <password> " . + "<quickAddText>\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} <username> <password> " . + "'Dinner at the beach on Thursday 8 PM'\n"; + } + break; + case 'createWebContentEvent': + if ($argc == 12) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + $id = createWebContentEvent($client, $argv[4], $argv[5], $argv[6], + $argv[7], $argv[8], $argv[9], $argv[10], $argv[11]); + print "Event created with ID: $id\n"; + } else { + echo "Usage: php {$argv[0]} {$argv[1]} <username> <password> " . + "<title> <startDate> <endDate> <icon> <url> <height> <width> <type>\n\n"; + echo "This creates a web content event on 2007/06/09.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} <username> <password> " . + "'World Cup 2006' '2007-06-09' '2007-06-10' " . + "'http://www.google.com/calendar/images/google-holiday.gif' " . + "'http://www.google.com/logos/worldcup06.gif' " . + "'120' '276' 'image/gif'\n"; + } + break; + case 'createRecurringEvent': + if ($argc == 7) { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + createRecurringEvent($client, $argv[4], $argv[5], $argv[6]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} <username> <password> " . + "<title> <description> <where>\n\n"; + echo "This creates an all-day event which occurs first on 2007/05/01" . + "and repeats weekly on Tuesdays until 2007/09/04\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} <username> <password> " . + "'Tennis with Beth' 'Meet for a quick lesson' 'On the courts'\n"; + } + break; + } +} else if (!isset($_SERVER["HTTP_HOST"])) { + // running from command line, but action left unspecified + echo "Usage: php {$argv[0]} <action> [<username>] [<password>] " . + "[<arg1> <arg2> ...]\n\n"; + echo "Possible action values include:\n" . + "outputCalendar\n" . + "outputCalendarMagicCookie\n" . + "outputCalendarByDateRange\n" . + "outputCalendarByFullTextQuery\n" . + "outputCalendarList\n" . + "updateEvent\n" . + "deleteEventById\n" . + "deleteEventByUrl\n" . + "createEvent\n" . + "createQuickAddEvent\n" . + "createWebContentEvent\n" . + "createRecurringEvent\n" . + "setReminder\n" . + "addExtendedProperty\n"; +} else { + // running through web server - demonstrate AuthSub + processPageLoad(); +} diff --git a/zend/demos/Zend/Gdata/Docs.php b/zend/demos/Zend/Gdata/Docs.php new file mode 100755 index 0000000..2d61ecc --- /dev/null +++ b/zend/demos/Zend/Gdata/Docs.php @@ -0,0 +1,940 @@ +<?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 + * @subpackage Demos + * @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 Google Documents List data API. Utilizes the + * Zend Framework Gdata components to communicate with the Google API. + * + * Requires the Zend Framework Gdata components and PHP >= 5.2.11 + * + * You can run this sample both from the command line (CLI) and also + * from a web browser. When running through a web browser, only + * AuthSub and outputting a list of documents is demonstrated. When + * running via CLI, all functionality except AuthSub is available and dependent + * upon the command line options passed. Run this script without any + * command line options to see usage, eg: + * /usr/local/bin/php -f Docs.php + * + * More information on the Command Line Interface is available at: + * http://www.php.net/features.commandline + * + * NOTE: You must ensure that Zend Framework is in your PHP include + * path. You can do this via php.ini settings, or by modifying the + * argument to set_include_path in the code below. + * + * NOTE: As this is sample code, not all of the functions do full error + * handling. + */ + +/** + * @see Zend_Loader + */ +require_once 'Zend/Loader.php'; + +/** + * @see Zend_Gdata + */ +Zend_Loader::loadClass('Zend_Gdata'); + +/** + * @see Zend_Gdata_AuthSub + */ +Zend_Loader::loadClass('Zend_Gdata_AuthSub'); + +/** + * @see Zend_Gdata_ClientLogin + */ +Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); + +/** + * @see Zend_Gdata_Docs + */ +Zend_Loader::loadClass('Zend_Gdata_Docs'); + +/** + * Returns a HTTP client object with the appropriate headers for communicating + * with Google using the ClientLogin credentials supplied. + * + * @param string $user The username, in e-mail address format, to authenticate + * @param string $pass The password for the user specified + * @return Zend_Http_Client + */ +function getClientLoginHttpClient($user, $pass) +{ + $service = Zend_Gdata_Docs::AUTH_SERVICE_NAME; + $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); + return $client; +} + +// ************************ BEGIN CLI SPECIFIC CODE ************************ + +/** + * Display list of valid commands. + * + * @param string $executable The name of the current script. This is usually available as $argv[0]. + * @return void + */ +function displayHelp($executable) +{ + echo "Usage: php {$executable} <action> [<username>] [<password>] " . + "[<arg1> <arg2> ...]\n\n"; + echo "Possible action values include:\n" . + "retrieveAllDocuments\n" . + "retrieveWPDocs\n" . + "retrieveSpreadsheets\n" . + "fullTextSearch\n" . + "uploadDocument\n"; +} + +/** + * Parse command line arguments and execute appropriate function when + * running from the command line. + * + * If no arguments are provided, usage information will be provided. + * + * @param array $argv The array of command line arguments provided by PHP. + * $argv[0] should be the current executable name or '-' if not available. + * @param integer $argc The size of $argv. + * @return void + */ +function runCLIVersion($argv, $argc) +{ + if (isset($argc) && $argc >= 2) { + # Prepare a server connection + if ($argc >= 4) { + try { + $client = getClientLoginHttpClient($argv[2], $argv[3]); + $docs = new Zend_Gdata_Docs($client); + } catch (Zend_Gdata_App_AuthException $e) { + echo "Error: Unable to authenticate. Please check your"; + echo " credentials.\n"; + exit(1); + } + } + + # Dispatch arguments to the desired method + switch ($argv[1]) { + case 'retrieveAllDocuments': + if ($argc >= 4) { + retrieveAllDocuments($docs, false); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} <username>"; + echo " <password>\n\n"; + echo "This lists all of the documents in the user's"; + echo " account.\n"; + } + break; + case 'retrieveWPDocs': + if ($argc >= 4) { + //echo "!WP Docs:"; + //var_dump($docs); + retrieveWPDocs($docs, false); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} <username>"; + echo " <password>\n\n"; + echo "This lists all of the word processing documents in"; + echo " the user's account.\n"; + } + break; + case 'retrieveSpreadsheets': + if ($argc >= 4) { + retrieveAllDocuments($docs, false); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} <username>"; + echo " <password>\n\n"; + echo "This lists all of the spreadsheets in the user's"; + echo " account.\n"; + } + break; + case 'fullTextSearch': + if ($argc >= 4) { + // Combine all of the query args into one query string. + // The command line split the query string on space + // characters. + $queryString = implode(' ', array_slice($argv, 4)); + fullTextSearch($docs, false, $queryString); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} <username>"; + echo " <password> <query string>\n\n"; + echo "This lists all of the documents which contain the"; + echo " query string.\n"; + } + break; + case 'uploadDocument': + if ($argc >= 5) { + // Pass in the file name of the document to be uploaded. + // Since the document is on this machine, we do not need + // to set the temporary file name. The temp file name is + // used only when uploading to a webserver. + uploadDocument($docs, false, $argv[4], null); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} <username>"; + echo " <password> <file_with_path>\n\n"; + echo "This lists all of the documents which contain the"; + echo " query string.\n"; + echo "\nExample: php {$argv[0]} {$argv[1]} <username>"; + echo " <password> /tmp/testSpreadsheet.ods\n"; + } + break; + default: + // Invalid action entered + displayHelp($argv[0]); + // End switch block + } + } else { + // action left unspecified + displayHelp($argv[0]); + } +} + +/** + * Displays the titles for the Google Documents entries in the feed. In HTML + * mode, the titles are links which point to the HTML version of the document. + * + * @param Zend_Gdata_Docs_DocumentListFeed $feed + * @param boolean $html True if output should be formatted for display in + * a web browser + * @return void + */ +function printDocumentsFeed($feed, $html) +{ + if ($html) {echo "<ul>\n";} + + // Iterate over the document entries in the feed and display each document's + // title. + foreach ($feed->entries as $entry) { + + if ($html) { + // Find the URL of the HTML view of the document. + $alternateLink = ''; + foreach ($entry->link as $link) { + if ($link->getRel() === 'alternate') { + $alternateLink = $link->getHref(); + } + } + // Make the title link to the document on docs.google.com. + echo "<li><a href=\"$alternateLink\">\n"; + } + + echo "$entry->title\n"; + + if ($html) {echo "</a></li>\n";} + } + + if ($html) {echo "</ul>\n";} +} + +/** + * Obtain a list of all of a user's docs.google.com documents and print the + * titles to the command line. + * + * @param Zend_Gdata_Docs $client The service object to use for communicating with the Google + * Documents server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @return void + */ +function retrieveAllDocuments($client, $html) +{ + if ($html) {echo "<h2>Your documents</h2>\n";} + + $feed = $client->getDocumentListFeed(); + + printDocumentsFeed($feed, $html); +} + +/** + * Obtain a list of all of a user's docs.google.com word processing + * documents and print the titles to the command line. + * + * @param Zend_Gdata_Docs $client The service object to use for communicating with the Google + * Documents server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @return void + */ +function retrieveWPDocs($client, $html) +{ + if ($html) {echo "<h2>Your word processing documents</h2>\n";} + + $feed = $client->getDocumentListFeed( + 'http://docs.google.com/feeds/documents/private/full/-/document'); + + printDocumentsFeed($feed, $html); +} + +/** + * Obtain a list of all of a user's docs.google.com spreadsheets + * documents and print the titles to the command line. + * + * @param Zend_Gdata_Docs $client The service object to use for communicating with the Google + * Documents server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @return void + */ +function retrieveSpreadsheets($client, $html) +{ + if ($html) {echo "<h2>Your spreadsheets</h2>\n";} + + $feed = $client->getDocumentListFeed( + 'http://docs.google.com/feeds/documents/private/full/-/spreadsheet'); + + printDocumentsFeed($feed, $html); +} + +/** + * Obtain a list of all of a user's docs.google.com documents + * which match the specified search criteria and print the titles to the + * command line. + * + * @param Zend_Gdata_Docs $client The service object to use for communicating with the Google + * Documents server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $query The search query to use + * @return void + */ +function fullTextSearch($client, $html, $query) +{ + if ($html) {echo "<h2>Documents containing $query</h2>\n";} + + $feed = $client->getDocumentListFeed( + 'http://docs.google.com/feeds/documents/private/full?q=' . $query); + + printDocumentsFeed($feed, $html); +} + +/** + * Upload the specified document + * + * @param Zend_Gdata_Docs $docs The service object to use for communicating with + * the Google Documents server. + * @param boolean $html True if output should be formatted for display in + * a web browser. + * @param string $originalFileName The name of the file to be uploaded. The mime type + * of the file is determined from the extension on + * this file name. For example, test.csv is uploaded + * as a comma seperated volume and converted into a + * spreadsheet. + * @param string $temporaryFileLocation (optional) The file in which the data for the + * document is stored. This is used when the file has + * been uploaded from the client's machine to the + * server and is stored in a temporary file which + * does not have an extension. If this parameter is + * null, the file is read from the originalFileName. + * @return void + */ +function uploadDocument($docs, $html, $originalFileName, + $temporaryFileLocation) { + $fileToUpload = $originalFileName; + if ($temporaryFileLocation) { + $fileToUpload = $temporaryFileLocation; + } + + // Upload the file and convert it into a Google Document. The original + // file name is used as the title of the document and the mime type + // is determined based on the extension on the original file name. + $newDocumentEntry = $docs->uploadFile($fileToUpload, $originalFileName, + null, Zend_Gdata_Docs::DOCUMENTS_LIST_FEED_URI); + + echo "New Document Title: "; + + if ($html) { + // Find the URL of the HTML view of this document. + $alternateLink = ''; + foreach ($newDocumentEntry->link as $link) { + if ($link->getRel() === 'alternate') { + $alternateLink = $link->getHref(); + } + } + // Make the title link to the document on docs.google.com. + echo "<a href=\"$alternateLink\">\n"; + } + echo $newDocumentEntry->title."\n"; + if ($html) {echo "</a>\n";} +} + +// ************************ BEGIN WWW SPECIFIC CODE ************************ + +/** + * Writes the HTML prologue for this app. + * + * NOTE: We would normally keep the HTML/CSS markup separate from the business + * logic above, but have decided to include it here for simplicity of + * having a single-file sample. + * + * + * @param boolean $displayMenu (optional) If set to true, a navigation menu is displayed at the top + * of the page. Default is true. + * @return void + */ +function startHTML($displayMenu = true) +{ +?> +<!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>Documents List API Demo + + + + + + + + + +
+'; + echo '← Back
'; + } +?> +
+ + + +
+

Almost there...

+

Before using this demo, you must set an application password + to protect your account. You will also need to set your + Google Apps credentials in order to communicate with the Google + Apps servers.

+

To continue, open this file in a text editor and fill + out the information in the configuration section.

+
+ +
+

Google Docs Authentication Failed

+

Authentication with the Google Apps servers failed.

+

Please open this file in a text editor and make + sure your credentials are correct.

+
+{$linkText}"; +} + +/** + * Returns the AuthSub URL which the user must visit to authenticate requests + * from this application. + * + * Uses getCurrentUrl() to get the next URL which the user will be redirected + * to after successfully authenticating with the Google service. + * + * @return string AuthSub URL + */ +function getAuthSubUrl() +{ + $next = getCurrentUrl(); + $scope = 'http://docs.google.com/feeds/documents'; + $secure = false; + $session = true; + return Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, + $session); +} + +/** + * Returns a HTTP client object with the appropriate headers for communicating + * with Google using AuthSub authentication. + * + * Uses the $_SESSION['sessionToken'] to store the AuthSub session token after + * it is obtained. The single use token supplied in the URL when redirected + * after the user succesfully authenticated to Google is retrieved from the + * $_GET['token'] variable. + * + * @return Zend_Http_Client + */ +function getAuthSubHttpClient() +{ + global $_SESSION, $_GET; + if (!isset($_SESSION['docsSampleSessionToken']) && isset($_GET['token'])) { + $_SESSION['docsSampleSessionToken'] = + Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']); + } + $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['docsSampleSessionToken']); + return $client; +} + +/** + * Returns the full URL of the current page, based upon env variables + * + * Env variables used: + * $_SERVER['HTTPS'] = (on|off|) + * $_SERVER['HTTP_HOST'] = value of the Host: header + * $_SERVER['SERVER_PORT'] = port number (only used if not http/80,https/443) + * $_SERVER['REQUEST_URI'] = the URI after the method of the HTTP request + * + * @return string Current URL + */ +function getCurrentUrl() +{ + global $_SERVER; + + /** + * Filter php_self to avoid a security vulnerability. + */ + $php_request_uri = 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 . $php_request_uri; +} + +/** + * Display the main menu for running in a web browser. + * + * @return void + */ +function displayMenu() +{ +?> +

Main Menu

+ +

Welcome to the Google Documents List API demo page. Please select + from one of the following three options to see a list of commands.

+ + + +

Tip: You can also run this demo from the command line if your system + has PHP CLI support enabled.

+ +

Logout

+ +

Logout successful.

+ + +Invalid mode.\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + } + } + + // Check for an invalid command. If so, display an error and exit. + if (!empty($_REQUEST['command'])) { + header('HTTP/1.1 400 Bad Request'); + startHTML(); + echo "

Invalid command.

\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + // If a menu parameter is available, display a submenu. + + if (!empty($_REQUEST['menu'])) { + switch ($_REQUEST['menu']) { + case 'list': + startHTML(); + displayListMenu(); + endHTML(); + case 'query': + startHTML(); + displayQueryMenu(); + endHTML(); + case 'upload': + startHTML(); + displayUploadMenu(); + endHTML(); + case 'logout': + startHTML(false); + logout(); + endHTML(); + default: + header('HTTP/1.1 400 Bad Request'); + startHTML(); + echo "

Invalid menu selection.

\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + } + // If we get this far, that means there's nothing to do. Display + // the main menu. + // If no command was issued and no menu was selected, display the + // main menu. + startHTML(); + displayMenu(); + endHTML(); + } +} + +/** + * Display the menu for running in a web browser. + * + * @return void + */ +function displayListMenu() +{ +?> +

List Documents Menu

+ +
+

Retrieve Google Documents Feed

+

Retrieve the feed for all of your documents.

+

+ +

+

+
+ +
+

Retrieve Google Word Processing Documents

+

Query the documents list feed for all word processing documents.

+

+ +

+

+
+ +
+

Retrieve Google Spreadsheets

+

Query the documents list feed for all spreadsheets.

+

+ +

+

+
+ +

Query the Documents List Feed

+ +
+

Search the Documents List Feed

+

Find documents which contain the desired text.

+

+ + +

+

+
+ + +

Upload a document

+ +
+

Select a Document to Upload

+

Upload a file from your computer to Google Documents.

+

+ + +

+

+
+ +Service Error Encountered

\n"; + echo "
" . htmlspecialchars($e->__toString()) . "
"; + endHTML(true); + } +} diff --git a/zend/demos/Zend/Gdata/Gapps.php b/zend/demos/Zend/Gdata/Gapps.php new file mode 100644 index 0000000..4f15ffe --- /dev/null +++ b/zend/demos/Zend/Gdata/Gapps.php @@ -0,0 +1,1992 @@ += 5.2.11 + * + * You can run this sample both from the command line (CLI) and also + * from a web browser. Run this script without any command line options to + * see usage, eg: + * /usr/bin/env php Gapps.php + * + * More information on the Command Line Interface is available at: + * http://www.php.net/features.commandline + * + * When running this code from a web browser, be sure to fill in your + * Google Apps credentials below and choose a password for authentication + * via the web browser. + * + * Since this is a demo, only minimal error handling and input validation + * are performed. THIS CODE IS FOR DEMONSTRATION PURPOSES ONLY. NOT TO BE + * USED IN A PRODUCTION ENVIRONMENT. + * + * NOTE: You must ensure that Zend Framework is in your PHP include + * path. You can do this via php.ini settings, or by modifying the + * argument to set_include_path in the code below. + */ + +// ************************ BEGIN WWW CONFIGURATION ************************ + +/** + * Google Apps username. This is the username (without domain) used + * to administer your Google Apps account. This value is only + * used when accessing this demo on a web server. + * + * For example, if you login to Google Apps as 'foo@bar.com.inavlid', + * your username is 'foo'. + */ +define('GAPPS_USERNAME', 'username'); + +/** + * Google Apps domain. This is the domain associated with your + * Google Apps account. This value is only used when accessing this demo + * on a web server. + * + * For example, if you login to Google Apps as foo@bar.com.inavlid, + * your domain is 'bar.com.invalid'. + */ +define('GAPPS_DOMAIN', 'example.com.invalid'); + +/** + * Google Apps password. This is the password associated with the above + * username. This value is only used when accessing this demo on a + * web server. + */ +define('GAPPS_PASSWORD', 'your password here'); + +/** + * Login password. This password is used to protect your account from + * unauthorized access when running this demo on a web server. + * + * If this field is blank, all access will be denied. A blank password + * field is not the same as no password (which is disallowed for + * security reasons). + * + * NOTE: While we could technically just ask the user for their Google Apps + * credentials, the ClientLogin API is not intended for direct use by + * web applications. If you are the only user of the application, this + * is fine--- but you should not ask other users to enter their + * credentials via your web application. + */ +define('LOGIN_PASSWORD', ''); + +// ************************* END WWW CONFIGURATION ************************* + +/** + * @see Zend_Loader + */ +require_once 'Zend/Loader.php'; + +/** + * @see Zend_Gdata + */ +Zend_Loader::loadClass('Zend_Gdata'); + +/** + * @see Zend_Gdata_ClientLogin + */ +Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); + +/** + * @see Zend_Gdata_Gapps + */ +Zend_Loader::loadClass('Zend_Gdata_Gapps'); + +/** + * Returns a HTTP client object with the appropriate headers for communicating + * with Google using the ClientLogin credentials supplied. + * + * @param string $user The username, in e-mail address format, to authenticate + * @param string $pass The password for the user specified + * @return Zend_Http_Client + */ +function getClientLoginHttpClient($user, $pass) +{ + $service = Zend_Gdata_Gapps::AUTH_SERVICE_NAME; + $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service); + return $client; +} + +/** + * Creates a new user for the current domain. The user will be created + * without admin privileges. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The desired username for the user. + * @param string $givenName The given name for the user. + * @param string $familyName The family name for the user. + * @param string $password The plaintext password for the user. + * @return void + */ +function createUser($gapps, $html, $username, $givenName, $familyName, + $password) +{ + if ($html) {echo "

Create User

\n";} + $gapps->createUser($username, $givenName, $familyName, + $password); + if ($html) {echo "

Done.

\n";} +} + +/** + * Retrieves a user for the current domain by username. Information about + * that user is then output. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The desired username for the user. + * @return void + */ +function retrieveUser($gapps, $html, $username) +{ + if ($html) {echo "

User Information

\n";} + + $user = $gapps->retrieveUser($username); + + if ($html) {echo '

';} + + if ($user !== null) { + echo ' Username: ' . $user->login->username; + if ($html) {echo '
';} + echo "\n"; + + echo ' Given Name: '; + if ($html) { + echo htmlspecialchars($user->name->givenName); + } else { + echo $user->name->givenName; + } + if ($html) {echo '
';} + echo "\n"; + + echo ' Family Name: '; + if ($html) { + echo htmlspecialchars($user->name->familyName); + } else { + echo $user->name->familyName; + } + if ($html) {echo '
';} + echo "\n"; + + echo ' Suspended: ' . ($user->login->suspended ? 'Yes' : 'No'); + if ($html) {echo '
';} + echo "\n"; + + echo ' Admin: ' . ($user->login->admin ? 'Yes' : 'No'); + if ($html) {echo '
';} + echo "\n"; + + echo ' Must Change Password: ' . + ($user->login->changePasswordAtNextLogin ? 'Yes' : 'No'); + if ($html) {echo '
';} + echo "\n"; + + echo ' Has Agreed To Terms: ' . + ($user->login->agreedToTerms ? 'Yes' : 'No'); + + } else { + echo 'Error: Specified user not found.'; + } + if ($html) {echo '

';} + echo "\n"; +} + +/** + * Retrieves the list of users for the current domain and outputs + * that list. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @return void + */ +function retrieveAllUsers($gapps, $html) +{ + if ($html) {echo "

Registered Users

\n";} + + $feed = $gapps->retrieveAllUsers(); + + if ($html) {echo "
    \n";} + + foreach ($feed as $user) { + if ($html) { + echo "
  • "; + } else { + echo " * "; + } + echo $user->login->username . ' ('; + if ($html) { + echo htmlspecialchars($user->name->givenName . ' ' . + $user->name->familyName); + } else { + echo $user->name->givenName . ' ' . $user->name->familyName; + } + echo ')'; + if ($html) {echo '
  • ';} + echo "\n"; + } + if ($html) {echo "
\n";} +} + +/** + * Change the name for an existing user. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be updated + * @param string $newGivenName The new given name for the user. + * @param string $newFamilyName The new family name for the user. + * @return void + */ +function updateUserName($gapps, $html, $username, $newGivenName, $newFamilyName) +{ + if ($html) {echo "

Update User Name

\n";} + + $user = $gapps->retrieveUser($username); + + if ($user !== null) { + $user->name->givenName = $newGivenName; + $user->name->familyName = $newFamilyName; + $user->save(); + } else { + if ($html) {echo '

';} + echo 'Error: Specified user not found.'; + if ($html) {echo '

';} + echo "\n"; + } + + if ($html) {echo "

Done.

\n";} +} + +/** + * Change the password for an existing user. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be updated + * @param string $newPassword The new password for the user. + * @return void + */ +function updateUserPassword($gapps, $html, $username, $newPassword) +{ + if ($html) {echo "

Update User Password

\n";} + + $user = $gapps->retrieveUser($username); + + if ($user !== null) { + $user->login->password = $newPassword; + $user->save(); + } else { + if ($html) {echo '

';} + echo 'Error: Specified user not found.'; + if ($html) {echo '

';} + echo "\n"; + } + + if ($html) {echo "

Done.

\n";} +} + +/** + * Suspend a given user. The user will not be able to login until restored. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be updated. + * @return void + */ +function suspendUser($gapps, $html, $username) +{ + if ($html) {echo "

Suspend User

\n";} + + $user = $gapps->retrieveUser($username); + + if ($user !== null) { + $user->login->suspended = true; + $user->save(); + } else { + if ($html) {echo '

';} + echo 'Error: Specified user not found.'; + if ($html) {echo '

';} + echo "\n"; + } + + if ($html) {echo "

Done.

\n";} +} + +/** + * Restore a given user after being suspended. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be updated. + * @return void + */ +function restoreUser($gapps, $html, $username) +{ + if ($html) {echo "

Restore User

\n";} + + $user = $gapps->retrieveUser($username); + + if ($user !== null) { + $user->login->suspended = false; + $user->save(); + } else { + if ($html) {echo '

';} + echo 'Error: Specified user not found.'; + if ($html) {echo '

';} + echo "\n"; + } + + if ($html) {echo "

Done.

\n";} +} + +/** + * Give a user admin rights. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be updated. + * @return void + */ +function giveUserAdminRights($gapps, $html, $username) +{ + if ($html) {echo "

Grant Administrative Rights

\n";} + + $user = $gapps->retrieveUser($username); + + if ($user !== null) { + $user->login->admin = true; + $user->save(); + } else { + if ($html) {echo '

';} + echo 'Error: Specified user not found.'; + if ($html) {echo '

';} + echo "\n"; + } + + if ($html) {echo "

Done.

\n";} +} + +/** + * Revoke a user's admin rights. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be updated. + * @return void + */ +function revokeUserAdminRights($gapps, $html, $username) +{ + if ($html) {echo "

Revoke Administrative Rights

\n";} + + $user = $gapps->retrieveUser($username); + + if ($user !== null) { + $user->login->admin = false; + $user->save(); + } else { + if ($html) {echo '

';} + echo 'Error: Specified user not found.'; + if ($html) {echo '

';} + echo "\n"; + } + + if ($html) {echo "

Done.

\n";} +} + +/** + * Force a user to change their password at next login. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be updated. + * @return void + */ +function setUserMustChangePassword($gapps, $html, $username) +{ + if ($html) {echo "

Force User To Change Password

\n";} + + $user = $gapps->retrieveUser($username); + + if ($user !== null) { + $user->login->changePasswordAtNextLogin = true; + $user->save(); + } else { + if ($html) {echo '

';} + echo 'Error: Specified user not found.'; + if ($html) {echo '

';} + echo "\n"; + } + + if ($html) {echo "

Done.

\n";} +} + +/** + * Undo forcing a user to change their password at next login. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be updated. + * @return void + */ +function clearUserMustChangePassword($gapps, $html, $username) +{ + if ($html) {echo "

Undo Force User To Change Password

\n";} + + $user = $gapps->retrieveUser($username); + + if ($user !== null) { + $user->login->changePasswordAtNextLogin = false; + $user->save(); + } else { + if ($html) {echo '

';} + echo 'Error: Specified user not found.'; + if ($html) {echo '

';} + echo "\n"; + } + + if ($html) {echo "

Done.

\n";} +} + +/** + * Delete the user who owns a given username. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username which should be deleted. + * @return void + */ +function deleteUser($gapps, $html, $username) +{ + if ($html) {echo "

Delete User

\n";} + + $gapps->deleteUser($username); + + if ($html) {echo "

Done.

\n";} +} + +/** + * Create a new nickname. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username to which the nickname should be assigned. + * @param string $nickname The name of the nickname to be created. + * @return void + */ +function createNickname($gapps, $html, $username, $nickname) +{ + if ($html) {echo "

Create Nickname

\n";} + + $gapps->createNickname($username, $nickname); + + if ($html) {echo "

Done.

\n";} +} + +/** + * Retrieve a specified nickname and output its ownership information. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $nickname The name of the nickname to be retrieved. + * @return void + */ +function retrieveNickname($gapps, $html, $nickname) +{ + if ($html) {echo "

Nickname Information

\n";} + + $nickname = $gapps->retrieveNickname($nickname); + + if ($html) {echo '

';} + + if ($nickname !== null) { + echo ' Nickname: ' . $nickname->nickname->name; + if ($html) {echo '
';} + echo "\n"; + + echo ' Owner: ' . $nickname->login->username; + } else { + echo 'Error: Specified nickname not found.'; + } + if ($html) {echo '

';} + echo "\n"; +} + +/** + * Outputs all nicknames owned by a specific username. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $username The username whose nicknames should be displayed. + * @return void + */ +function retrieveNicknames($gapps, $html, $username) +{ + if ($html) {echo "

Registered Nicknames For {$username}

\n";} + + $feed = $gapps->retrieveNicknames($username); + + if ($html) {echo "
    \n";} + + foreach ($feed as $nickname) { + if ($html) { + echo "
  • "; + } else { + echo " * "; + } + echo $nickname->nickname->name; + if ($html) {echo '
  • ';} + echo "\n"; + } + if ($html) {echo "
\n";} +} + + +/** + * Retrieves the list of nicknames for the current domain and outputs + * that list. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @return void + */ +function retrieveAllNicknames($gapps, $html) +{ + if ($html) {echo "

Registered Nicknames

\n";} + + $feed = $gapps->retrieveAllNicknames(); + + if ($html) {echo "
    \n";} + + foreach ($feed as $nickname) { + if ($html) { + echo "
  • "; + } else { + echo " * "; + } + echo $nickname->nickname->name . ' => ' . $nickname->login->username; + if ($html) {echo '
  • ';} + echo "\n"; + } + if ($html) {echo "
\n";} +} + +/** + * Delete's a specific nickname from the current domain. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $nickname The nickname that should be deleted. + * @return void + */ +function deleteNickname($gapps, $html, $nickname) +{ + if ($html) {echo "

Delete Nickname

\n";} + + $gapps->deleteNickname($nickname); + + if ($html) {echo "

Done.

\n";} + +} + +/** + * Create a new email list. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $emailList The name of the email list to be created. + * @return void + */ +function createEmailList($gapps, $html, $emailList) +{ + if ($html) {echo "

Create Email List

\n";} + + $gapps->createEmailList($emailList); + + if ($html) {echo "

Done.

\n";} +} + +/** + * Outputs the list of email lists to which the specified address is + * subscribed. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $recipient The email address of the recipient whose subscriptions should + * be retrieved. Only a username is required if the recipient is a + * member of the current domain. + * @return void + */ +function retrieveEmailLists($gapps, $html, $recipient) +{ + if ($html) {echo "

Email List Subscriptions For {$recipient}

\n";} + + $feed = $gapps->retrieveEmailLists($recipient); + + if ($html) {echo "
    \n";} + + foreach ($feed as $list) { + if ($html) { + echo "
  • "; + } else { + echo " * "; + } + echo $list->emailList->name; + if ($html) {echo '
  • ';} + echo "\n"; + } + if ($html) {echo "
\n";} +} + +/** + * Outputs the list of all email lists on the current domain. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @return void + */ +function retrieveAllEmailLists($gapps, $html) +{ + if ($html) {echo "

Registered Email Lists

\n";} + + $feed = $gapps->retrieveAllEmailLists(); + + if ($html) {echo "
    \n";} + + foreach ($feed as $list) { + if ($html) { + echo "
  • "; + } else { + echo " * "; + } + echo $list->emailList->name; + if ($html) {echo '
  • ';} + echo "\n"; + } + if ($html) {echo "
\n";} +} + +/** + * Delete's a specific email list from the current domain. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $emailList The email list that should be deleted. + * @return void + */ +function deleteEmailList($gapps, $html, $emailList) +{ + if ($html) {echo "

Delete Email List

\n";} + + $gapps->deleteEmailList($emailList); + + if ($html) {echo "

Done.

\n";} +} + +/** + * Add a recipient to an existing email list. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the + * Google Apps server. + * @param boolean $html True if output should be formatted for display in a + * web browser. + * @param string $recipientAddress The address of the recipient who should be added. + * @param string $emailList The name of the email address the recipient be added to. + * @return void + */ +function addRecipientToEmailList($gapps, $html, $recipientAddress, + $emailList) +{ + if ($html) {echo "

Subscribe Recipient

\n";} + + $gapps->addRecipientToEmailList($recipientAddress, $emailList); + + if ($html) {echo "

Done.

\n";} +} + +/** + * Outputs the list of all recipients for a given email list. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the Google + * Apps server. + * @param boolean $html True if output should be formatted for display in a web browser. + * @param string $emailList The email list whose recipients should be output. + * @return void + */ +function retrieveAllRecipients($gapps, $html, $emailList) +{ + if ($html) {echo "

Email List Recipients For {$emailList}

\n";} + + $feed = $gapps->retrieveAllRecipients($emailList); + + if ($html) {echo "
    \n";} + + foreach ($feed as $recipient) { + if ($html) { + echo "
  • "; + } else { + echo " * "; + } + echo $recipient->who->email; + if ($html) {echo '
  • ';} + echo "\n"; + } + if ($html) {echo "
\n";} +} + +/** + * Remove an existing recipient from an email list. + * + * @param Zend_Gdata_Gapps $gapps The service object to use for communicating with the + * Google Apps server. + * @param boolean $html True if output should be formatted for display in a + * web browser. + * @param string $recipientAddress The address of the recipient who should be removed. + * @param string $emailList The email list from which the recipient should be removed. + * @return void + */ +function removeRecipientFromEmailList($gapps, $html, $recipientAddress, + $emailList) +{ + if ($html) {echo "

Unsubscribe Recipient

\n";} + + $gapps->removeRecipientFromEmailList($recipientAddress, $emailList); + + if ($html) {echo "

Done.

\n";} + +} + +// ************************ BEGIN CLI SPECIFIC CODE ************************ + +/** + * Display list of valid commands. + * + * @param string $executable The name of the current script. This is usually available as $argv[0]. + * @return void + */ +function displayHelp($executable) +{ + echo "Usage: php {$executable} [] [] " . + "[ ...]\n\n"; + echo "Possible action values include:\n" . + "createUser\n" . + "retrieveUser\n" . + "retrieveAllUsers\n" . + "updateUserName\n" . + "updateUserPassword\n" . + "suspendUser\n" . + "restoreUser\n" . + "giveUserAdminRights\n" . + "revokeUserAdminRights\n" . + "setUserMustChangePassword\n" . + "clearUserMustChangePassword\n" . + "deleteUser\n" . + "createNickname\n" . + "retrieveNickname\n" . + "retrieveNicknames\n" . + "retrieveAllNicknames\n" . + "deleteNickname\n" . + "createEmailList\n" . + "retrieveEmailLists\n" . + "retrieveAllEmailLists\n" . + "deleteEmailList\n" . + "addRecipientToEmailList\n" . + "retrieveAllRecipients\n" . + "removeRecipientFromEmailList\n"; +} + +/** + * Parse command line arguments and execute appropriate function when + * running from the command line. + * + * If no arguments are provided, usage information will be provided. + * + * @param array $argv The array of command line arguments provided by PHP. + * $argv[0] should be the current executable name or '-' if not available. + * @param integer $argc The size of $argv. + * @return void + */ +function runCLIVersion($argv, $argc) +{ + if (isset($argc) && $argc >= 2) { + # Prepare a server connection + if ($argc >= 5) { + try { + $client = getClientLoginHttpClient($argv[2] . '@' . $argv[3], $argv[4]); + $gapps = new Zend_Gdata_Gapps($client, $argv[3]); + } catch (Zend_Gdata_App_AuthException $e) { + echo "Error: Unable to authenticate. Please check your credentials.\n"; + exit(1); + } + } + + # Dispatch arguments to the desired method + switch ($argv[1]) { + case 'createUser': + if ($argc == 9) { + createUser($gapps, false, $argv[5], $argv[6], $argv[7], $argv[8]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n\n"; + echo "This creates a new user with the given username.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe John Doe p4ssw0rd\n"; + } + break; + case 'retrieveUser': + if ($argc == 6) { + retrieveUser($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "This retrieves the user with the specified " . + "username and displays information about that user.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'retrieveAllUsers': + if ($argc == 5) { + retrieveAllUsers($gapps, false); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "This lists all users on the current domain.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} \n"; + } + break; + case 'updateUserName': + if ($argc == 8) { + updateUserName($gapps, false, $argv[5], $argv[6], $argv[7]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n\n"; + echo "Renames an existing user.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe Jane Doe\n"; + } + break; + case 'updateUserPassword': + if ($argc == 7) { + updateUserPassword($gapps, false, $argv[5], $argv[6]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n\n"; + echo "Changes the password for an existing user.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe password1\n"; + } + break; + case 'suspendUser': + if ($argc == 6) { + suspendUser($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "This suspends the given user.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'restoreUser': + if ($argc == 6) { + restoreUser($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "This restores the given user after being suspended.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'giveUserAdminRights': + if ($argc == 6) { + giveUserAdminRights($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Give a user admin rights for this domain.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'revokeUserAdminRights': + if ($argc == 6) { + revokeUserAdminRights($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Remove a user's admin rights for this domain.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'setUserMustChangePassword': + if ($argc == 6) { + setUserMustChangePassword($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Force a user to change their password at next login.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'clearUserMustChangePassword': + if ($argc == 6) { + clearUserMustChangePassword($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Clear the flag indicating that a user must change " . + "their password at next login.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'deleteUser': + if ($argc == 6) { + deleteUser($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Delete the user who owns a given username.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'createNickname': + if ($argc == 7) { + createNickname($gapps, false, $argv[5], $argv[6]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n\n"; + echo "Create a new nickname for the specified user.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe johnny\n"; + } + break; + case 'retrieveNickname': + if ($argc == 6) { + retrieveNickname($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Retrieve a nickname and display its ownership " . + "information.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "johnny\n"; + } + break; + case 'retrieveNicknames': + if ($argc == 6) { + retrieveNicknames($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Output all nicknames owned by a specific username.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "jdoe\n"; + } + break; + case 'retrieveAllNicknames': + if ($argc == 5) { + retrieveAllNicknames($gapps, false); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Output all registered nicknames on the system.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "\n"; + } + break; + case 'deleteNickname': + if ($argc == 6) { + deleteNickname($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Delete a specific nickname.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "johnny\n"; + } + break; + case 'createEmailList': + if ($argc == 6) { + createEmailList($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Create a new email list with the specified name.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "friends\n"; + } + break; + case 'retrieveEmailLists': + if ($argc == 6) { + retrieveEmailLists($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Retrieve all email lists to which the specified " . + "address is subscribed.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "johnny@somewhere.com.invalid\n"; + } + break; + case 'retrieveAllEmailLists': + if ($argc == 5) { + retrieveAllEmailLists($gapps, false); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Retrieve a list of all email lists on the current " . + "domain.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "\n"; + } + break; + case 'deleteEmailList': + if ($argc == 6) { + deleteEmailList($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Delete a specified email list.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "friends\n"; + } + break; + case 'addRecipientToEmailList': + if ($argc == 7) { + addRecipientToEmailList($gapps, false, $argv[5], $argv[6]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n\n"; + echo "Add a recipient to an existing email list.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "johnny@somewhere.com.invalid friends\n"; + } + break; + case 'retrieveAllRecipients': + if ($argc == 6) { + retrieveAllRecipients($gapps, false, $argv[5]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + "\n\n"; + echo "Retrieve all recipients for an existing email list.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "friends\n"; + } + break; + case 'removeRecipientFromEmailList': + if ($argc == 7) { + removeRecipientFromEmailList($gapps, false, $argv[5], $argv[6]); + } else { + echo "Usage: php {$argv[0]} {$argv[1]} " . + " \n\n"; + echo "Remove an existing recipient from an email list.\n"; + echo "EXAMPLE: php {$argv[0]} {$argv[1]} " . + "johnny@somewhere.com.invalid friends\n"; + } + break; + default: + // Invalid action entered + displayHelp($argv[0]); + // End switch block + } + } else { + // action left unspecified + displayHelp($argv[0]); + } +} + +// ************************ BEGIN WWW SPECIFIC CODE ************************ + +/** + * Writes the HTML prologue for this app. + * + * NOTE: We would normally keep the HTML/CSS markup separate from the business + * logic above, but have decided to include it here for simplicity of + * having a single-file sample. + * + * + * @param boolean $displayMenu (optional) If set to true, a navigation + * menu is displayed at the top of the page. Default is true. + * @return void + */ +function startHTML($displayMenu = true) +{ +?> + + + + + + + Google Apps Provisioning API Demo + + + + + + + + + +
+← Back'; + } +?> +
+ + + +
+

Almost there...

+

Before using this demo, you must set an application password + to protect your account. You will also need to set your + Google Apps credentials in order to communicate with the Google + Apps servers.

+

To continue, open this file in a text editor and fill + out the information in the configuration section.

+
+ +
+

Google Apps Authentication Failed

+

Authentication with the Google Apps servers failed.

+

Please open this file in a text editor and make + sure your credentials are correct.

+
+ +
+

Authentication Required

+ ' . $errorText . "\n"; + } + ?> +

Please enter your login password to continue.

+

+

+

Notice: This application is for demonstration + purposes only. Not for use in a production environment.

+

+
+ +

Main Menu

+ +

Welcome to the Google Apps Provisioning API demo page. Please select + from one of the following three options to see a list of commands.

+ + + +

Tip: You can also run this demo from the command line if your system + has PHP CLI support enabled.

+ +

User Maintenance Menu

+ +
+

Create User

+

Create a new user with the given properties.

+

+ + +
+ +
+ +
+ + +

+ +

+
+
+

Retrieve User

+

Retrieve the information for an existing user.

+

+ + +
+

+ +

+
+
+

Retrieve All Users

+

Retrieve the list of all users on the current domain.

+

+ +

+ +

+
+
+

Update Name

+

Update the name for an existing user.

+

+ + +
+ +
+ +
+

+ +

+
+
+

Update Password

+

Update the password for an existing user.

+

+ + +
+ +

+

+ +

+
+
+

Suspend/Restore User

+

Mark an existing user as suspended or restore a suspended user. + While suspended, the user will be prohibited from logging into + this domain.

+

+ + + +

+
+ User may log into + this domain.
+ User + may not log into this domain. +
+ +

+
+
+

Issue/Revoke Admin Rights

+

Set whether an existing user has administrative rights for the current + domain.

+

+ + + +

+
+ User + may administer this domain.
+ User + may not administer this domain. +
+ +

+
+
+

Force User To Change Password

+

Set whether an existing user must change their password at + their next login.

+

+ + + +

+
+ User is required to + change their password at next login.
+ User is + not required to change their password at next + login. +
+ +

+
+
+

Delete User

+

Delete an existing user on the current domain.

+

+ + +
+

+ +

+
+ +

Nickname Maintenance Menu

+ +
+

Create Nickname

+

Create a nickname for an existing user.

+

+ + +
+ +
+

+ +

+
+
+

Retrieve Nickname

+

Retrieve the information for an existing nickname.

+

+ + +
+

+ +

+
+
+

Retrieve Nicknames

+

Retrieve the nicknames associated with an existing username.

+

+ + +
+

+ +

+
+
+

Retrieve All Nicknames

+

Retrieve the nicknames on the current domain.

+

+ +

+ +

+
+
+

Delete Nickname

+

Delete an existing nickname from the current domain.

+

+ + +
+

+ +

+
+ +

Email List Maintenance Menu

+ +
+

Create Email List

+

Create a new email list for the current domain.

+

+ + +
+

+ +

+
+
+

Retrieve Email Lists

+

Retrieve all email lists to which a given email address is + subscribed.

+

+ + +
+

+ +

+
+
+

Retrieve All Email Lists

+

Retrieve all email lists on the current domain.

+

+ +

+ +

+
+
+

Delete Email List

+

Delete an existing email list from the current domain.

+

+ + +
+

+ +

+
+
+

Add Recipient To Email List

+

Add or remove a recipient from an existing email list. A complete + email address is required for recipients outside the current + domain.

+

+ + +
+ +
+

+ Subscribe + recipient.
+ Unsubscribe recipient. +
+

+ +

+
+
+

Retrieve All Recipients

+

Retrieve all recipients subscribed to an existing email list.

+

+ + +
+

+ +

+
+ +

Logout

+ +

Logout successful.

+ + +Invalid mode.\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + case 'setUserAdmin': + if ($_POST['mode'] == 'issue') { + startHTML(); + giveUserAdminRights($gapps, true, $_POST['user']); + endHTML(true); + } elseif ($_POST['mode'] == 'revoke') { + startHTML(); + revokeUserAdminRights($gapps, true, $_POST['user']); + endHTML(true); + } else { + header('HTTP/1.1 400 Bad Request'); + startHTML(); + echo "

Invalid mode.

\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + case 'setForceChangePassword': + if ($_POST['mode'] == 'set') { + startHTML(); + setUserMustChangePassword($gapps, true, $_POST['user']); + endHTML(true); + } elseif ($_POST['mode'] == 'clear') { + startHTML(); + clearUserMustChangePassword($gapps, true, $_POST['user']); + endHTML(true); + } else { + header('HTTP/1.1 400 Bad Request'); + startHTML(); + echo "

Invalid mode.

\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + case 'deleteUser': + startHTML(); + deleteUser($gapps, true, $_POST['user']); + endHTML(true); + case 'createNickname': + startHTML(); + createNickname($gapps, true, $_POST['user'], + $_POST['nickname']); + endHTML(true); + case 'deleteNickname': + startHTML(); + deleteNickname($gapps, true, $_POST['nickname']); + endHTML(true); + case 'createEmailList': + startHTML(); + createEmailList($gapps, true, $_POST['emailList']); + endHTML(true); + case 'deleteEmailList': + startHTML(); + deleteEmailList($gapps, true, $_POST['emailList']); + endHTML(true); + case 'modifySubscription': + if ($_POST['mode'] == 'subscribe') { + startHTML(); + addRecipientToEmailList($gapps, true, $_POST['recipient'], + $_POST['emailList']); + endHTML(true); + } elseif ($_POST['mode'] == 'unsubscribe') { + startHTML(); + removeRecipientFromEmailList($gapps, true, + $_POST['recipient'], $_POST['emailList']); + endHTML(true); + } else { + header('HTTP/1.1 400 Bad Request'); + startHTML(); + echo "

Invalid mode.

\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + } + } + + // Check for an invalid command. If so, display an error and exit. + if (!empty($_REQUEST['command'])) { + header('HTTP/1.1 400 Bad Request'); + startHTML(); + echo "

Invalid command.

\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + + // If a menu parameter is available, display a submenu. + if (!empty($_REQUEST['menu'])) { + switch ($_REQUEST['menu']) { + case 'user': + startHTML(); + displayUserMenu(); + endHTML(); + case 'nickname': + startHTML(); + displayNicknameMenu(); + endHTML(); + case 'emailList': + startHTML(); + displayEmailListMenu(); + endHTML(); + case 'logout': + startHTML(false); + logout(); + endHTML(); + default: + header('HTTP/1.1 400 Bad Request'); + startHTML(); + echo "

Invalid menu selection.

\n"; + echo "

Please check your request and try again.

"; + endHTML(true); + } + } + + // If we get this far, that means there's nothing to do. Display + // the main menu. + // If no command was issued and no menu was selected, display the + // main menu. + startHTML(); + displayMenu(); + endHTML(); +} + +// ************************** PROGRAM ENTRY POINT ************************** + +if (!isset($_SERVER["HTTP_HOST"])) { + // running through command line + runCLIVersion($argv, $argc); +} else { + // running through web server + try { + runWWWVersion(); + } catch (Zend_Gdata_Gapps_ServiceException $e) { + // Try to recover gracefully from a service exception. + // The HTML prologue will have already been sent. + echo "

Service Error Encountered

\n"; + echo "
" . htmlspecialchars($e->__toString()) . "
"; + endHTML(true); + } +} diff --git a/zend/demos/Zend/Gdata/InstallationChecker.php b/zend/demos/Zend/Gdata/InstallationChecker.php new file mode 100644 index 0000000..ab975a2 --- /dev/null +++ b/zend/demos/Zend/Gdata/InstallationChecker.php @@ -0,0 +1,386 @@ + array( + 'tested' => false, 'errors' => null), + self::ZEND_GDATA_INSTALL_ERRORS => array( + 'tested' => false, 'errors' => null), + self::SSL_CAPABILITIES_ERRORS => array( + 'tested' => false, 'errors' => null), + self::YOUTUBE_API_CONNECTIVITY_ERRORS => array( + 'tested' => false, 'errors' => null) + ); + + private $_sapiModeCLI = null; + + /** + * Create a new InstallationChecker object and run verifications. + * @return void + */ + public function __construct() + { + $this->determineIfInCLIMode(); + $this->runAllVerifications(); + $this->outputResults(); + } + + /** + * Set the sapiModeCLI variable to true if we are running CLI mode. + * + * @return void + */ + private function determineIfInCLIMode() + { + if (php_sapi_name() == 'cli') { + $this->_sapiModeCLI = true; + } + } + + /** + * Getter for sapiModeCLI variable. + * + * @return boolean True if we are running in CLI mode. + */ + public function runningInCLIMode() + { + if ($this->_sapiModeCLI) { + return true; + } else { + return false; + } + } + + /** + * Run verifications, stopping at each step if there is a failure. + * + * @return void + */ + public function runAllVerifications() + { + if (!$this->validatePHPExtensions()) { + return; + } + if (!$this->validateZendFrameworkInstallation()) { + return; + } + if (!$this->testSSLCapabilities()) { + return; + } + if (!$this->validateYouTubeAPIConnectivity()) { + return; + } + } + + /** + * Validate that the required PHP Extensions are installed and available. + * + * @return boolean False if there were errors. + */ + private function validatePHPExtensions() + { + $phpExtensionErrors = array(); + foreach (self::$REQUIRED_EXTENSIONS as $requiredExtension) { + if (!extension_loaded($requiredExtension)) { + $requiredExtensionError = $requiredExtension . + ' extension missing'; + $documentationLink = null; + if ($requiredExtension != 'standard') { + $documentationLink = self::PHP_MANUAL_LINK_FRAGMENT . + $requiredExtension . '.php'; + $documentationLink = + $this->checkAndAddHTMLLink($documentationLink); + } else { + $documentationLink = self::PHP_MANUAL_LINK_FRAGMENT . + 'spl.php'; + $documentationLink = + $this->checkAndAddHTMLLink($documentationLink); + } + + if ($documentationLink) { + $phpExtensionErrors[] = $requiredExtensionError . + ' - refer to ' . $documentationLink; + } + } + } + $this->_allErrors[self::PHP_EXTENSION_ERRORS]['tested'] = true; + if (count($phpExtensionErrors) > 0) { + $this->_allErrors[self::PHP_EXTENSION_ERRORS]['errors'] = + $phpExtensionErrors; + return false; + } + return true; + } + + /** + * Validate that the Gdata component of Zend Framework is installed + * properly. Also checks that the required YouTube API helper methods are + * found. + * + * @return boolean False if there were errors. + */ + private function validateZendFrameworkInstallation() + { + $zendFrameworkInstallationErrors = array(); + $zendLoaderPresent = false; + try { + $zendLoaderPresent = @fopen('Zend/Loader.php', 'r', true); + } catch (Exception $e) { + $zendFrameworkInstallationErrors[] = 'Exception thrown trying to ' . + 'access Zend/Loader.php using \'use_include_path\' = true ' . + 'Make sure you include the Zend Framework in your ' . + 'include_path which currently contains: "' . + ini_get('include_path') . '"'; + } + + if ($zendLoaderPresent) { + @fclose($zendLoaderPresent); + require_once('Zend/Loader.php'); + require_once('Zend/Version.php'); + Zend_Loader::loadClass('Zend_Gdata_YouTube'); + Zend_Loader::loadClass('Zend_Gdata_YouTube_VideoEntry'); + $yt = new Zend_Gdata_YouTube(); + $videoEntry = $yt->newVideoEntry(); + if (!method_exists($videoEntry, 'setVideoTitle')) { + $zendFrameworkMessage = 'Your version of the ' . + 'Zend Framework ' . Zend_Version::VERSION . ' is too old' . + ' to run the YouTube demo application and does not' . + ' contain the new helper methods. Please check out a' . + ' newer version from Zend\'s repository: ' . + checkAndAddHTMLLink(self::ZEND_SUBVERSION_URI); + $zendFrameworkInstallationErrors[] = $zendFrameworkMessage; + } + } else { + if (count($zendFrameworkInstallationErrors) < 1) { + $zendFrameworkInstallationErrors[] = 'Exception thrown trying' . + ' to access Zend/Loader.php using \'use_include_path\' =' . + ' true. Make sure you include Zend Framework in your' . + ' include_path which currently contains: ' . + ini_get('include_path'); + } + } + + $this->_allErrors[self::ZEND_GDATA_INSTALL_ERRORS]['tested'] = true; + + if (count($zendFrameworkInstallationErrors) > 0) { + $this->_allErrors[self::ZEND_GDATA_INSTALL_ERRORS]['errors'] = + $zendFrameworkInstallationErrors; + return false; + } + return true; + } + + /** + * Create HTML link from an input string if not in CLI mode. + * + * @param string The error message to be converted to a link. + * @return string Either the original error message or an HTML version. + */ + private function checkAndAddHTMLLink($inputString) { + if (!$this->runningInCLIMode()) { + return $this->makeHTMLLink($inputString); + } else { + return $inputString; + } + } + + /** + * Create an HTML link from a string. + * + * @param string The string to be made into link text and anchor target. + * @return string HTML link. + */ + private function makeHTMLLink($inputString) + { + return '' . + $inputString . ''; + } + + /** + * Validate that SSL Capabilities are available. + * + * @return boolean False if there were errors. + */ + private function testSSLCapabilities() + { + $sslCapabilitiesErrors = array(); + require_once 'Zend/Loader.php'; + Zend_Loader::loadClass('Zend_Http_Client'); + + $httpClient = new Zend_Http_Client( + 'https://www.google.com/accounts/AuthSubRequest'); + $response = $httpClient->request(); + $this->_allErrors[self::SSL_CAPABILITIES_ERRORS]['tested'] = true; + + if ($response->isError()) { + $sslCapabilitiesErrors[] = 'Response from trying to access' . + ' \'https://www.google.com/accounts/AuthSubRequest\' ' . + $response->getStatus() . ' - ' . $response->getMessage(); + } + + if (count($sslCapabilitiesErrors) > 0) { + $this->_allErrors[self::SSL_CAPABILITIES_ERRORS]['errors'] = + $sslCapabilitiesErrors; + return false; + } + return true; + } + + /** + * Validate that we can connect to the YouTube API. + * + * @return boolean False if there were errors. + */ + private function validateYouTubeAPIConnectivity() + { + $connectivityErrors = array(); + require_once 'Zend/Loader.php'; + Zend_Loader::loadClass('Zend_Gdata_YouTube'); + $yt = new Zend_Gdata_YouTube(); + $topRatedFeed = $yt->getTopRatedVideoFeed(); + if ($topRatedFeed instanceof Zend_Gdata_YouTube_VideoFeed) { + if ($topRatedFeed->getTotalResults()->getText() < 1) { + $connectivityErrors[] = 'There was less than 1 video entry' . + ' in the \'Top Rated Video Feed\''; + } + } else { + $connectivityErrors[] = 'The call to \'getTopRatedVideoFeed()\' ' . + 'did not result in a Zend_Gdata_YouTube_VideoFeed object'; + } + + $this->_allErrors[self::YOUTUBE_API_CONNECTIVITY_ERRORS]['tested'] = + true; + if (count($connectivityErrors) > 0) { + $this->_allErrors[self::YOUTUBE_API_CONNECTIVITY_ERRORS]['tested'] = + $connectivityErrors; + return false; + } + return true; + } + + /** + * Dispatch a call to outputResultsInHTML or outputResultsInText pending + * the current SAPI mode. + * + * @return void + */ + public function outputResults() + { + if ($this->_sapiModeCLI) { + print $this->getResultsInText(); + } else { + print $this->getResultsInHTML(); + } + } + + + /** + * Return a string representing the results of the verifications. + * + * @return string A string representing the results. + */ + private function getResultsInText() + { + $output = "== Ran PHP Installation Checker using CLI ==\n"; + + $error_count = 0; + foreach($this->_allErrors as $key => $value) { + $output .= $key . ' -- '; + if (($value['tested'] == true) && (count($value['errors']) == 0)) { + $output .= "No errors found\n"; + } elseif ($value['tested'] == true) { + $output .= "Tested\n"; + $error_count = 0; + foreach ($value['errors'] as $error) { + $output .= "Error number: " . $error_count . "\n--" . + $error . "\n"; + } + } else { + $output .= "Not tested\n"; + } + $error_count++; + } + return $output; + } + + /** + * Return an HTML table representing the results of the verifications. + * + * @return string An HTML string representing the results. + */ + private function getResultsInHTML() + { + $html = "\n". + "\nPHP Installation Checker\n" . + "\n" . + "\n" . + "\n"; + + $error_count = 0; + foreach($this->_allErrors as $key => $value) { + $html .= ""; + if (($value['tested'] == true) && (count($value['errors']) == 0)) { + $html .= "\n" . + "\n"; + } elseif ($value['tested'] == true) { + $html .= "\n"; + $error_count = 0; + foreach ($value['errors'] as $error) { + $html .= "" . + "\n"; + } + } else { + $html .= "\n"; + } + $error_count++; + } + $html .= ""; + return $html; + } +} + +$installationChecker = new InstallationChecker(); diff --git a/zend/demos/Zend/Gdata/MyLibrary/demo.php b/zend/demos/Zend/Gdata/MyLibrary/demo.php new file mode 100755 index 0000000..33045c5 --- /dev/null +++ b/zend/demos/Zend/Gdata/MyLibrary/demo.php @@ -0,0 +1,226 @@ +getMessage() ."\nCredentials provided were ". + "email: [$email] and password [$password].\n"); + } + $this->gdClient = new Zend_Gdata_Books($client); + } + + /** + * Print the content of a feed + * + * @param Zend_Gdata_Gbase_Feed $feed + * @return void + */ + public function printFeed($feed) + { + $i = 0; + foreach($feed as $entry) { + $titles = $entry->getTitles(); + $rating = $entry->getRating(); + if (count($titles)) { + if (!is_object($rating)) { + $rating_str = "?"; + } else { + $rating_str = $rating->getAverage(); + } + print $i." ".$titles[0]->getText(). + ", Rating: ".$rating_str."\n"; + $i++; + } + } + } + + /** + * List books in the My library feed + * + * @return void + */ + public function listLibrary() + { + $feed = $this->gdClient->getUserLibraryFeed(); + print "== Books in my library ==\n"; + $this->printFeed($feed); + print "\n"; + } + + /** + * List books in the annotation feed. + * + * @return void + */ + public function listReviewed() + { + $feed = $this->gdClient->getUserLibraryFeed( + Zend_Gdata_Books::MY_ANNOTATION_FEED_URI); + print "== Books I annotated ==\n"; + $this->printFeed($feed); + print "\n"; + } + + /** + * Add an arbitrary book to the library feed. + * + * @param string $volumeId Volume to the library + * @return void + */ + public function addBookToLibrary($volumeId) + { + $entry = new Zend_Gdata_Books_VolumeEntry(); + $entry->setId( + new Zend_Gdata_App_Extension_Id($volumeId)); + print "Inserting ".$volumeId."\n\n"; + return $this->gdClient->insertVolume($entry); + } + + /** + * Add an arbitrary book to the library feed. + * + * @param string $volumeId Volume to add a rating to + * @param float $rating Numeric rating from 0 to 5 + * @return void + */ + public function addRating($volumeId, $rating) + { + $entry = new Zend_Gdata_Books_VolumeEntry(); + $entry->setId( + new Zend_Gdata_App_Extension_Id($volumeId)); + $entry->setRating( + new Zend_Gdata_Extension_Rating($rating, "0", 5, 1)); + print "Inserting a rating of ".$rating." for ".$volumeId."\n\n"; + return $this->gdClient->insertVolume($entry, + Zend_Gdata_Books::MY_ANNOTATION_FEED_URI); + } + + /** + * Remove an an arbitrary book from a feed (either remove + * from library feed or remove the annotations from annotation + * feed). + * + * @param Zend_Gdata_Books_VolumeEntry $entry + * @return void + */ + public function removeBook($entry) + { + print "Deleting ".$entry->getId()->getText()."\n\n"; + $this->gdClient->deleteVolume($entry); + } + + /** + * Main logic for the demo. + * + * @return void + */ + public function run() + { + $test_volume = "8YEAAAAAYAAJ"; + + // Playing with the library feed + $this->listLibrary(); + + $entry = $this->addBookToLibrary($test_volume); + $this->listLibrary(); + + $this->removeBook($entry); + $this->listLibrary(); + + // Playing with the annotation feed + $this->listReviewed(); + + $entry = $this->addRating($test_volume, 4.0); + $this->listReviewed(); + + $this->removeBook($entry); + $this->listReviewed(); + } +} + +/** + * getInput + * + * @param string $text + * @return string + */ +function getInput($text) +{ + echo $text.': '; + return trim(fgets(STDIN)); +} + +echo "Books Gdata API - my library demo\n\n"; +$email = null; +$pass = null; + +// process command line options +foreach ($argv as $argument) { + $argParts = explode('=', $argument); + if ($argParts[0] == '--email') { + $email = $argParts[1]; + } else if ($argParts[0] == '--pass') { + $pass = $argParts[1]; + } +} + +if (($email == null) || ($pass == null)) { + $email = getInput( + "Please enter your email address [example: username@gmail.com]"); + $pass = getInput( + "Please enter your password [example: mypassword]"); +} + +$demo = new SimpleDemo($email, $pass); +$demo->run(); diff --git a/zend/demos/Zend/Gdata/Photos.php b/zend/demos/Zend/Gdata/Photos.php new file mode 100755 index 0000000..4c3e257 --- /dev/null +++ b/zend/demos/Zend/Gdata/Photos.php @@ -0,0 +1,904 @@ += 5.2.11 + * + * You can run this sample from a web browser. + * + * NOTE: You must ensure that Zend Framework is in your PHP include + * path. You can do this via php.ini settings, or by modifying the + * argument to set_include_path in the code below. + * + * NOTE: As this is sample code, not all of the functions do full error + * handling. + */ + +/** + * @see Zend_Loader + */ +require_once 'Zend/Loader.php'; + +/** + * @see Zend_Gdata + */ +Zend_Loader::loadClass('Zend_Gdata'); + +/** + * @see Zend_Gdata_AuthSub + */ +Zend_Loader::loadClass('Zend_Gdata_AuthSub'); + +/** + * @see Zend_Gdata_Photos + */ +Zend_Loader::loadClass('Zend_Gdata_Photos'); + +/** + * @see Zend_Gdata_Photos_UserQuery + */ +Zend_Loader::loadClass('Zend_Gdata_Photos_UserQuery'); + +/** + * @see Zend_Gdata_Photos_AlbumQuery + */ +Zend_Loader::loadClass('Zend_Gdata_Photos_AlbumQuery'); + +/** + * @see Zend_Gdata_Photos_PhotoQuery + */ +Zend_Loader::loadClass('Zend_Gdata_Photos_PhotoQuery'); + +/** + * @see Zend_Gdata_App_Extension_Category + */ +Zend_Loader::loadClass('Zend_Gdata_App_Extension_Category'); + +session_start(); + + +/** + * Adds a new photo to the specified album + * + * @param Zend_Http_Client $client The authenticated client + * @param string $user The user's account name + * @param integer $albumId The album's id + * @param array $photo The uploaded photo + * @return void + */ +function addPhoto($client, $user, $albumId, $photo) +{ + $photos = new Zend_Gdata_Photos($client); + + $fd = $photos->newMediaFileSource($photo["tmp_name"]); + $fd->setContentType($photo["type"]); + + $entry = new Zend_Gdata_Photos_PhotoEntry(); + $entry->setMediaSource($fd); + $entry->setTitle($photos->newTitle($photo["name"])); + + $albumQuery = new Zend_Gdata_Photos_AlbumQuery; + $albumQuery->setUser($user); + $albumQuery->setAlbumId($albumId); + + $albumEntry = $photos->getAlbumEntry($albumQuery); + + $result = $photos->insertPhotoEntry($entry, $albumEntry); + if ($result) { + outputAlbumFeed($client, $user, $albumId); + } else { + echo "There was an issue with the file upload."; + } +} + +/** + * Deletes the specified photo + * + * @param Zend_Http_Client $client The authenticated client + * @param string $user The user's account name + * @param integer $albumId The album's id + * @param integer $photoId The photo's id + * @return void + */ +function deletePhoto($client, $user, $albumId, $photoId) +{ + $photos = new Zend_Gdata_Photos($client); + + $photoQuery = new Zend_Gdata_Photos_PhotoQuery; + $photoQuery->setUser($user); + $photoQuery->setAlbumId($albumId); + $photoQuery->setPhotoId($photoId); + $photoQuery->setType('entry'); + + $entry = $photos->getPhotoEntry($photoQuery); + + $photos->deletePhotoEntry($entry, true); + + outputAlbumFeed($client, $user, $albumId); +} + +/** + * Adds a new album to the specified user's album + * + * @param Zend_Http_Client $client The authenticated client + * @param string $user The user's account name + * @param string $name The name of the new album + * @return void + */ +function addAlbum($client, $user, $name) +{ + $photos = new Zend_Gdata_Photos($client); + + $entry = new Zend_Gdata_Photos_AlbumEntry(); + $entry->setTitle($photos->newTitle($name)); + + $result = $photos->insertAlbumEntry($entry); + if ($result) { + outputUserFeed($client, $user); + } else { + echo "There was an issue with the album creation."; + } +} + +/** + * Deletes the specified album + * + * @param Zend_Http_Client $client The authenticated client + * @param string $user The user's account name + * @param integer $albumId The album's id + * @return void + */ +function deleteAlbum($client, $user, $albumId) +{ + $photos = new Zend_Gdata_Photos($client); + + $albumQuery = new Zend_Gdata_Photos_AlbumQuery; + $albumQuery->setUser($user); + $albumQuery->setAlbumId($albumId); + $albumQuery->setType('entry'); + + $entry = $photos->getAlbumEntry($albumQuery); + + $photos->deleteAlbumEntry($entry, true); + + outputUserFeed($client, $user); +} + +/** + * Adds a new comment to the specified photo + * + * @param Zend_Http_Client $client The authenticated client + * @param string $user The user's account name + * @param integer $albumId The album's id + * @param integer $photoId The photo's id + * @param string $comment The comment to add + * @return void + */ +function addComment($client, $user, $album, $photo, $comment) +{ + $photos = new Zend_Gdata_Photos($client); + + $entry = new Zend_Gdata_Photos_CommentEntry(); + $entry->setTitle($photos->newTitle($comment)); + $entry->setContent($photos->newContent($comment)); + + $photoQuery = new Zend_Gdata_Photos_PhotoQuery; + $photoQuery->setUser($user); + $photoQuery->setAlbumId($album); + $photoQuery->setPhotoId($photo); + $photoQuery->setType('entry'); + + $photoEntry = $photos->getPhotoEntry($photoQuery); + + $result = $photos->insertCommentEntry($entry, $photoEntry); + if ($result) { + outputPhotoFeed($client, $user, $album, $photo); + } else { + echo "There was an issue with the comment creation."; + } +} + +/** + * Deletes the specified comment + * + * @param Zend_Http_Client $client The authenticated client + * @param string $user The user's account name + * @param integer $albumId The album's id + * @param integer $photoId The photo's id + * @param integer $commentId The comment's id + * @return void + */ +function deleteComment($client, $user, $albumId, $photoId, $commentId) +{ + $photos = new Zend_Gdata_Photos($client); + + $photoQuery = new Zend_Gdata_Photos_PhotoQuery; + $photoQuery->setUser($user); + $photoQuery->setAlbumId($albumId); + $photoQuery->setPhotoId($photoId); + $photoQuery->setType('entry'); + + $path = $photoQuery->getQueryUrl() . '/commentid/' . $commentId; + + $entry = $photos->getCommentEntry($path); + + $photos->deleteCommentEntry($entry, true); + + outputPhotoFeed($client, $user, $albumId, $photoId); +} + +/** + * Adds a new tag to the specified photo + * + * @param Zend_Http_Client $client The authenticated client + * @param string $user The user's account name + * @param integer $album The album's id + * @param integer $photo The photo's id + * @param string $tag The tag to add to the photo + * @return void + */ +function addTag($client, $user, $album, $photo, $tag) +{ + $photos = new Zend_Gdata_Photos($client); + + $entry = new Zend_Gdata_Photos_TagEntry(); + $entry->setTitle($photos->newTitle($tag)); + + $photoQuery = new Zend_Gdata_Photos_PhotoQuery; + $photoQuery->setUser($user); + $photoQuery->setAlbumId($album); + $photoQuery->setPhotoId($photo); + $photoQuery->setType('entry'); + + $photoEntry = $photos->getPhotoEntry($photoQuery); + + $result = $photos->insertTagEntry($entry, $photoEntry); + if ($result) { + outputPhotoFeed($client, $user, $album, $photo); + } else { + echo "There was an issue with the tag creation."; + } +} + +/** + * Deletes the specified tag + * + * @param Zend_Http_Client $client The authenticated client + * @param string $user The user's account name + * @param integer $albumId The album's id + * @param integer $photoId The photo's id + * @param string $tagContent The name of the tag to be deleted + * @return void + */ +function deleteTag($client, $user, $albumId, $photoId, $tagContent) +{ + $photos = new Zend_Gdata_Photos($client); + + $photoQuery = new Zend_Gdata_Photos_PhotoQuery; + $photoQuery->setUser($user); + $photoQuery->setAlbumId($albumId); + $photoQuery->setPhotoId($photoId); + $query = $photoQuery->getQueryUrl() . "?kind=tag"; + + $photoFeed = $photos->getPhotoFeed($query); + + foreach ($photoFeed as $entry) { + if ($entry instanceof Zend_Gdata_Photos_TagEntry) { + if ($entry->getContent() == $tagContent) { + $tagEntry = $entry; + } + } + } + + $photos->deleteTagEntry($tagEntry, true); + + outputPhotoFeed($client, $user, $albumId, $photoId); +} + +/** + * Returns the path to the current script, without any query params + * + * Env variables used: + * $_SERVER['PHP_SELF'] + * + * @return string Current script path + */ +function getCurrentScript() +{ + global $_SERVER; + return $_SERVER["PHP_SELF"]; +} + +/** + * Returns the full URL of the current page, based upon env variables + * + * Env variables used: + * $_SERVER['HTTPS'] = (on|off|) + * $_SERVER['HTTP_HOST'] = value of the Host: header + * $_SERVER['SERVER_PORT'] = port number (only used if not http/80,https/443) + * $_SERVER['REQUEST_URI'] = the URI after the method of the HTTP request + * + * @return string Current URL + */ +function getCurrentUrl() +{ + global $_SERVER; + + /** + * Filter php_self to avoid a security vulnerability. + */ + $php_request_uri = 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 . $php_request_uri; +} + +/** + * Returns the AuthSub URL which the user must visit to authenticate requests + * from this application. + * + * Uses getCurrentUrl() to get the next URL which the user will be redirected + * to after successfully authenticating with the Google service. + * + * @return string AuthSub URL + */ +function getAuthSubUrl() +{ + $next = getCurrentUrl(); + $scope = 'http://picasaweb.google.com/data'; + $secure = false; + $session = true; + return Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure, + $session); +} + +/** + * Outputs a request to the user to login to their Google account, including + * a link to the AuthSub URL. + * + * Uses getAuthSubUrl() to get the URL which the user must visit to authenticate + * + * @return void + */ +function requestUserLogin($linkText) +{ + $authSubUrl = getAuthSubUrl(); + echo "{$linkText}"; +} + +/** + * Returns a HTTP client object with the appropriate headers for communicating + * with Google using AuthSub authentication. + * + * Uses the $_SESSION['sessionToken'] to store the AuthSub session token after + * it is obtained. The single use token supplied in the URL when redirected + * after the user succesfully authenticated to Google is retrieved from the + * $_GET['token'] variable. + * + * @return Zend_Http_Client + */ +function getAuthSubHttpClient() +{ + global $_SESSION, $_GET; + if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) { + $_SESSION['sessionToken'] = + Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']); + } + $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']); + return $client; +} + +/** + * Processes loading of this sample code through a web browser. Uses AuthSub + * authentication and outputs a list of a user's albums if succesfully + * authenticated. + * + * @return void + */ +function processPageLoad() +{ + global $_SESSION, $_GET; + if (!isset($_SESSION['sessionToken']) && !isset($_GET['token'])) { + requestUserLogin('Please login to your Google Account.'); + } else { + $client = getAuthSubHttpClient(); + if (!empty($_REQUEST['command'])) { + switch ($_REQUEST['command']) { + case 'retrieveSelf': + outputUserFeed($client, "default"); + break; + case 'retrieveUser': + outputUserFeed($client, $_REQUEST['user']); + break; + case 'retrieveAlbumFeed': + outputAlbumFeed($client, $_REQUEST['user'], $_REQUEST['album']); + break; + case 'retrievePhotoFeed': + outputPhotoFeed($client, $_REQUEST['user'], $_REQUEST['album'], + $_REQUEST['photo']); + break; + } + } + + // Now we handle the potentially destructive commands, which have to + // be submitted by POST only. + if (!empty($_POST['command'])) { + switch ($_POST['command']) { + case 'addPhoto': + addPhoto($client, $_POST['user'], $_POST['album'], $_FILES['photo']); + break; + case 'deletePhoto': + deletePhoto($client, $_POST['user'], $_POST['album'], + $_POST['photo']); + break; + case 'addAlbum': + addAlbum($client, $_POST['user'], $_POST['name']); + break; + case 'deleteAlbum': + deleteAlbum($client, $_POST['user'], $_POST['album']); + break; + case 'addComment': + addComment($client, $_POST['user'], $_POST['album'], $_POST['photo'], + $_POST['comment']); + break; + case 'addTag': + addTag($client, $_POST['user'], $_POST['album'], $_POST['photo'], + $_POST['tag']); + break; + case 'deleteComment': + deleteComment($client, $_POST['user'], $_POST['album'], + $_POST['photo'], $_POST['comment']); + break; + case 'deleteTag': + deleteTag($client, $_POST['user'], $_POST['album'], $_POST['photo'], + $_POST['tag']); + break; + default: + break; + } + } + + // If a menu parameter is available, display a submenu. + if (!empty($_REQUEST['menu'])) { + switch ($_REQUEST['menu']) { + case 'user': + displayUserMenu(); + break; + case 'photo': + displayPhotoMenu(); + break; + case 'album': + displayAlbumMenu(); + break; + case 'logout': + logout(); + break; + default: + header('HTTP/1.1 400 Bad Request'); + echo "

Invalid menu selection.

\n"; + echo "

Please check your request and try again.

"; + } + } + + if (empty($_REQUEST['menu']) && empty($_REQUEST['command'])) { + displayMenu(); + } + } +} + +/** + * Displays the main menu, allowing the user to select from a list of actions. + * + * @return void + */ +function displayMenu() +{ +?> +

Main Menu

+ +

Welcome to the Photos API demo page. Please select + from one of the following four options to fetch information.

+ + +
"; + echo "<< Back"; +} + +/** + * Displays the user menu, allowing the user to request a specific user's feed. + * + * @return void + */ +function displayUserMenu() +{ +?> +

User Menu

+ + + +

Photo Menu

+ + + +

Album Menu

+ + +setUser($user); + + $userFeed = $photos->getUserFeed(null, $query); + echo "

User Feed for: " . $userFeed->getTitle() . "

"; + echo "
\n"; + + echo "

Add an Album

"; +?> + + + + + + +setUser($user); + $query->setAlbumId($albumId); + + $albumFeed = $photos->getAlbumFeed($query); + echo "

Album Feed for: " . $albumFeed->getTitle() . "

"; + echo "
\n"; + + echo "

Add a Photo

"; +?> + + + + + + Please select a photo to upload:
+ + +setUser($user); + $query->setAlbumId($albumId); + $query->setPhotoId($photoId); + $query = $query->getQueryUrl() . "?kind=comment,tag"; + + $photoFeed = $photos->getPhotoFeed($query); + echo "

Photo Feed for: " . $photoFeed->getTitle() . "

"; + $thumbs = $photoFeed->getMediaGroup()->getThumbnail(); + echo ""; + + echo "

Comments:

"; + echo "
    \n"; + foreach ($photoFeed as $entry) { + if ($entry instanceof Zend_Gdata_Photos_CommentEntry) { + echo "\t
  • " . $entry->getContent(); + echo "
    "; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo "
  • \n"; + } + } + echo "
\n"; + echo "

Add a Comment

"; +?> + + + + + + + + +"; + echo "

Tags:

"; + echo "
    \n"; + foreach ($photoFeed as $entry) { + if ($entry instanceof Zend_Gdata_Photos_TagEntry) { + echo "\t
  • " . $entry->getTitle(); + echo "
    "; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo "
  • \n"; + } + } + echo "
\n"; + echo "

Add a Tag

"; +?> + + + + + + + + + + +getMessage() ."\nCredentials provided were email: [$email] and password [$password].\n"); + } + + $this->gdClient = new Zend_Gdata_Spreadsheets($client); + $this->currKey = ''; + $this->currWkshtId = ''; + $this->listFeed = ''; + $this->rowCount = 0; + $this->columnCount = 0; + } + + /** + * promptForSpreadsheet + * + * @return void + */ + public function promptForSpreadsheet() + { + $feed = $this->gdClient->getSpreadsheetFeed(); + print "== Available Spreadsheets ==\n"; + $this->printFeed($feed); + $input = getInput("\nSelection"); + $currKey = explode('/', $feed->entries[$input]->id->text); + $this->currKey = $currKey[5]; + } + + /** + * promptForWorksheet + * + * @return void + */ + public function promptForWorksheet() + { + $query = new Zend_Gdata_Spreadsheets_DocumentQuery(); + $query->setSpreadsheetKey($this->currKey); + $feed = $this->gdClient->getWorksheetFeed($query); + print "== Available Worksheets ==\n"; + $this->printFeed($feed); + $input = getInput("\nSelection"); + $currWkshtId = explode('/', $feed->entries[$input]->id->text); + $this->currWkshtId = $currWkshtId[8]; + + } + + /** + * promptForCellsAction + * + * @return void + */ + public function promptForCellsAction() + { + echo "Pick a command:\n"; + echo "\ndump -- dump cell information\nupdate {row} {col} {input_value} -- update cell information\n"; + $input = getInput('Command'); + $command = explode(' ', $input); + if ($command[0] == 'dump') { + $this->cellsGetAction(); + } else if (($command[0] == 'update') && (count($command) > 2)) { + $this->getRowAndColumnCount(); + if (count($command) == 4) { + $this->cellsUpdateAction($command[1], $command[2], $command[3]); + } elseif (count($command) > 4) { + $newValue = implode(' ', array_slice($command,3)); + $this->cellsUpdateAction($command[1], $command[2], $newValue); + } else { + $this->cellsUpdateAction($command[1], $command[2], ''); + } + } else { + $this->invalidCommandError($input); + } + } + + /** + * promptToResize + * + * @param integer $newRowCount + * @param integer $newColumnCount + * @return boolean + */ + public function promptToResize($newRowCount, $newColumnCount) { + $input = getInput('Would you like to resize the worksheet? [yes | no]'); + if ($input == 'yes') { + return $this->resizeWorksheet($newRowCount, $newColumnCount); + } else { + return false; + } + } + + /** + * resizeWorksheet + * + * @param integer $newRowCount + * @param integer $newColumnCount + * @return boolean + */ + public function resizeWorksheet($newRowCount, $newColumnCount) { + $query = new Zend_Gdata_Spreadsheets_DocumentQuery(); + $query->setSpreadsheetKey($this->currKey); + $query->setWorksheetId($this->currWkshtId); + $currentWorksheet = $this->gdClient->getWorksheetEntry($query); + $currentWorksheet = $currentWorksheet->setRowCount(new Zend_Gdata_Spreadsheets_Extension_RowCount($newRowCount)); + $currentWorksheet = $currentWorksheet->setColumnCount(new Zend_Gdata_Spreadsheets_Extension_ColCount($newColumnCount)); + $currentWorksheet->save(); + $this->getRowAndColumnCount(); + print "Worksheet has been resized to $this->rowCount rows and $this->columnCount columns.\n"; + return true; + } + + /** + * promptForListAction + * + * @return void + */ + public function promptForListAction() + { + echo "\n== Options ==\n". + "dump -- dump row information\n". + "insert {row_data} -- insert data in the next available cell in a given column (example: insert column_header=content)\n". + "update {row_index} {row_data} -- update data in the row provided (example: update row-number column-header=newdata\n". + "delete {row_index} -- delete a row\n\n"; + + $input = getInput('Command'); + $command = explode(' ', $input); + if ($command[0] == 'dump') { + $this->listGetAction(); + } else if ($command[0] == 'insert') { + $this->listInsertAction(array_slice($command, 1)); + } else if ($command[0] == 'update') { + $this->listUpdateAction($command[1], array_slice($command, 2)); + } else if ($command[0] == 'delete') { + $this->listDeleteAction($command[1]); + } else { + $this->invalidCommandError($input); + } + } + + /** + * cellsGetAction + * + * @return void + */ + public function cellsGetAction() + { + $query = new Zend_Gdata_Spreadsheets_CellQuery(); + $query->setSpreadsheetKey($this->currKey); + $query->setWorksheetId($this->currWkshtId); + $feed = $this->gdClient->getCellFeed($query); + $this->printFeed($feed); + } + + /** + * cellsUpdateAction + * + * @param integer $row + * @param integer $col + * @param string $inputValue + * @return void + */ + public function cellsUpdateAction($row, $col, $inputValue) + { + if (($row > $this->rowCount) || ($col > $this->columnCount)) { + print "Current worksheet only has $this->rowCount rows and $this->columnCount columns.\n"; + if (!$this->promptToResize($row, $col)) { + return; + } + } + $entry = $this->gdClient->updateCell($row, $col, $inputValue, + $this->currKey, $this->currWkshtId); + if ($entry instanceof Zend_Gdata_Spreadsheets_CellEntry) { + echo "Success!\n"; + } + } + + /** + * listGetAction + * + * @return void + */ + public function listGetAction() + { + $query = new Zend_Gdata_Spreadsheets_ListQuery(); + $query->setSpreadsheetKey($this->currKey); + $query->setWorksheetId($this->currWkshtId); + $this->listFeed = $this->gdClient->getListFeed($query); + print "entry id | row-content in column A | column-header: cell-content\n". + "Please note: The 'dump' command on the list feed only dumps data until the first blank row is encountered.\n\n"; + + $this->printFeed($this->listFeed); + print "\n"; + } + + /** + * listInsertAction + * + * @param mixed $rowData + * @return void + */ + public function listInsertAction($rowData) + { + $rowArray = $this->stringToArray($rowData); + $entry = $this->gdClient->insertRow($rowArray, $this->currKey, $this->currWkshtId); + if ($entry instanceof Zend_Gdata_Spreadsheets_ListEntry) { + foreach ($rowArray as $column_header => $value) { + echo "Success! Inserted '$value' in column '$column_header' at row ". substr($entry->getTitle()->getText(), 5) ."\n"; + } + } + } + + /** + * listUpdateAction + * + * @param integer $index + * @param mixed $rowData + * @return void + */ + public function listUpdateAction($index, $rowData) + { + $query = new Zend_Gdata_Spreadsheets_ListQuery(); + $query->setSpreadsheetKey($this->currKey); + $query->setWorksheetId($this->currWkshtId); + $this->listFeed = $this->gdClient->getListFeed($query); + $rowArray = $this->stringToArray($rowData); + $entry = $this->gdClient->updateRow($this->listFeed->entries[$index], $rowArray); + if ($entry instanceof Zend_Gdata_Spreadsheets_ListEntry) { + echo "Success!\n"; $response = $entry->save(); + + } + } + + /** + * listDeleteAction + * + * @param integer $index + * @return void + */ + public function listDeleteAction($index) + { + $query = new Zend_Gdata_Spreadsheets_ListQuery(); + $query->setSpreadsheetKey($this->currKey); + $query->setWorksheetId($this->currWkshtId); + $this->listFeed = $this->gdClient->getListFeed($query); + $this->gdClient->deleteRow($this->listFeed->entries[$index]); + } + + /** + * stringToArray + * + * @param string $rowData + * @return array + */ + public function stringToArray($rowData) + { + $arr = array(); + foreach ($rowData as $row) { + $temp = explode('=', $row); + $arr[$temp[0]] = $temp[1]; + } + return $arr; + } + + /** + * printFeed + * + * @param Zend_Gdata_Gbase_Feed $feed + * @return void + */ + public function printFeed($feed) + { + $i = 0; + foreach($feed->entries as $entry) { + if ($entry instanceof Zend_Gdata_Spreadsheets_CellEntry) { + print $entry->title->text .' '. $entry->content->text . "\n"; + } else if ($entry instanceof Zend_Gdata_Spreadsheets_ListEntry) { + print $i .' '. $entry->title->text .' | '. $entry->content->text . "\n"; + } else { + print $i .' '. $entry->title->text . "\n"; + } + $i++; + } + } + + /** + * getRowAndColumnCount + * + * @return void + */ + public function getRowAndColumnCount() + { + $query = new Zend_Gdata_Spreadsheets_CellQuery(); + $query->setSpreadsheetKey($this->currKey); + $query->setWorksheetId($this->currWkshtId); + $feed = $this->gdClient->getCellFeed($query); + + if ($feed instanceOf Zend_Gdata_Spreadsheets_CellFeed) { + $this->rowCount = $feed->getRowCount(); + $this->columnCount = $feed->getColumnCount(); + } + } + + /** + * invalidCommandError + * + * @param string $input + * @return void + */ + public function invalidCommandError($input) + { + echo 'Invalid input: '.$input."\n"; + } + + /** + * promtForFeedtype + * + * @return void + */ + public function promptForFeedtype() { + + $input = getInput('Select to use either the cell or the list feed [cells or list]'); + + if ($input == 'cells') { + while(1) { + $this->promptForCellsAction(); + } + } else if ($input == 'list') { + while(1) { + $this->promptForListAction(); + } + } else { + print "Invalid input. Please try again.\n"; + $this->promptForFeedtype(); + } + } + + /** + * run + * + * @return void + */ + public function run() + { + $this->promptForSpreadsheet(); + $this->promptForWorksheet(); + $this->promptForFeedtype(); + } +} + +/** + * getInput + * + * @param string $text + * @return string + */ +function getInput($text) +{ + echo $text.': '; + return trim(fgets(STDIN)); +} + +$email = null; +$pass = null; + +// process command line options +foreach ($argv as $argument) { + $argParts = explode('=', $argument); + if ($argParts[0] == '--email') { + $email = $argParts[1]; + } else if ($argParts[0] == '--pass') { + $pass = $argParts[1]; + } +} + +if (($email == null) || ($pass == null)) { + $email = getInput("Please enter your email address [example: username@gmail.com]"); + $pass = getInput("Please enter your password [example: mypassword]"); +} + +$sample = new SimpleCRUD($email, $pass); +$sample->run(); 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 @@ += 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'] = ''; + +/** + * 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 . + ') (check details)'; + break; + default: + echo 'There seems to have been an error: '. $code . + '(check details)'; + } +} + +/** + * 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 <<

Authenticated Actions

+ +END; +} +?> + + + + + YouTube data API Video Browser in PHP + + + + + +
+
+

YouTube data API Video App in PHP

+ click to examine session variables
+ +
+ +
+
+ +
Authentication status: + +END; + } else { + print <<Click here to generate authentication link +
+END; + } + ?> +
+ +
+ ' . + uploadStatus($_GET['status'], $code, $id) . + '
'; + } + ?> + + + +
+
+
+
+
+ + + + +
+
+
+
+
+
+ + + 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 Binary files /dev/null and b/zend/demos/Zend/Gdata/YouTubeVideoApp/notfound.jpg 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 @@ += 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

' + . '' + . 'click here to view details of last request
'; + return; + } catch (Zend_Gdata_App_Exception $e) { + print 'ERROR - Could not retrieve users video feed: ' + . $e->getMessage() . '
'; + 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 + . '
' . 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() . '
'; + 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

' + . '' + . 'click here to view details of last request
'; + return; + } catch (Zend_Gdata_App_Exception $e) { + print 'ERROR - Could not post video meta-data: ' . $e->getMessage(); + return; + } + print 'Entry updated successfully.
' + . '(refresh your video listing)
' + . 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

' + . '' + . 'click here to view details of last request
'; + return; + } catch (Zend_Gdata_App_Exception $e) { + print 'ERROR - Could not retrieve token for syndicated upload. ' + . $e->getMessage() + . '
' + . 'click here to view details of last request
'; + return; + } + + $tokenValue = $tokenArray['token']; + $postUrl = $tokenArray['url']; + + // place to redirect user after upload + if (!$nextUrl) { + $nextUrl = $_SESSION['homeUrl']; + } + + print <<< END +
+ + + + +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 . '
'; + 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

' + . '' + . 'click here to view details of last request
'; + return; + } catch (Zend_Gdata_App_Exception $e) { + print 'ERROR - Could not delete video: '. $e->getMessage(); + return; + } + + print 'Entry deleted succesfully.
' . $httpResponse->getBody() + . '
(refresh your video listing)
' + . 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 'Click here to authenticate with YouTube'; +} + +/** + * 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 ''; + } +} + +/** + * 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 = '
Ran PHP Installation Checker on " . + gmdate('c') . "
" . $key . "Tested
No errors found
Tested
" . $error_count . "" . $error . "
Not tested
'; + $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 .= '' + . '' + . ''; + $results++; + } + + if ($results < 1) { + echo '
No results found

'; + } else { + echo $table .'
'. stripslashes($videoTitle) . '' + . '

' + . stripslashes($videoDescription) . '

' + . '

category: ' . $videoCategory + . '

tagged: ' + . htmlspecialchars(implode(', ', $videoTags)) . '

'; + + if ($authenticated) { + $table .= '

' + . 'edit video data | ' + . 'delete this video


'; + } + + $table .= '

'; + } +} + +/** + * 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

' + . '' + . 'click here to view details of last request
'; + return; + } + + $videoTitle = htmlspecialchars($entry->getVideoTitle()); + $videoUrl = htmlspecialchars(findFlashUrl($entry)); + $relatedVideoFeed = getRelatedVideos($entry->getVideoId()); + $topRatedFeed = getTopRatedVideosByUser($entry->author[0]->name); + + print <<$videoTitle
+ + + + + +END; + + echo '
'; + echoVideoMetadata($entry); + echo '
Related:
'; + echoThumbnails($relatedVideoFeed); + echo '
Top rated videos by user:
'; + 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 <<Title: ${title}
+ Description: ${description}
+ Author: ${authorUsername}
+ Tags: ${tags}
+ Duration: ${duration} seconds
+ View count: ${viewCount}
+ Rating: ${rating} (${numRaters} ratings)
+ Flash: ${flashUrl}
+ Watch page: ${watchPage}
+END; +} + +/** + * Print message about YouTube caching. + * + * @return string A message + */ +function printCacheWarning() +{ + return '

' + . 'Please note that the change may not be reflected in the API ' + . 'immediately due to caching.
' + . 'Please refer to the API documentation for more details.

'; +} + +/** + * 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
'. + printCacheWarning(); + return; + } + + $playlistEntries = '
    '; + $entriesFound = 0; + foreach($feed as $entry) { + $playlistTitle = $entry->getTitleValue(); + $playlistDescription = $entry->getDescription()->getText(); + $playlistEntries .= '
  • ' . $playlistTitle + . '

    ' . $playlistDescription . ' | ' + . 'update | ' + . 'delete
  • '; + $entriesFound++; + } + + $playlistEntries .= '

' + . 'Add new playlist
' + . '
'; + + 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
' + . 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

' + . '' + . 'click here to view details of last request
'; + return; + } catch (Zend_Gdata_App_Exception $e) { + print 'ERROR - Could not create new playlist: ' . $e->getMessage(); + return; + } + + print 'Playlist added succesfully.
(refresh your playlist listing)
' + . 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
' + . 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

' + . '' + . 'click here to view details of last request
'; + return; + } catch (Zend_Gdata_App_Exception $e) { + print 'ERROR - Could not delete the playlist: ' . $e->getMessage(); + return; + } + + print 'Playlist deleted succesfully.
' + . '' + . '(refresh your playlist listing)
' . 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
' + . 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

' + . '' + . 'click here to view details of last request
'; + return; + } catch (Zend_Gdata_App_Exception $e) { + print 'ERROR - Could not delete the playlist: ' . $e->getMessage(); + return; + } + + print 'Playlist deleted succesfully.
(refresh your playlist listing)
'. + 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 @@ += 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(); +?> + + + YouTube data API Video Browser in PHP - Session Viewer + + + + +
+
+

Session variables


+
+ $value) { + + print '

'. $key . '

'. $value .'

'. + '
' . + ''. + ''. + '

'; +} +?> +
+back +
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 = 'Loading...'; + } 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 = ['
', + 'Enter video title:

', + 'Enter video description:

', + 'Select a category:
', + 'Enter some tags to describe your video ', + '(separated by spaces):
', + '
', + '', + '
'].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 = ['
', + 'Enter a new video title:
', + '
', + 'Enter a new video description:
', + '
', + 'Select a new category:
', + 'Enter some new tags to describe your video ', + '(separated by spaces):
', + '
', + '
', + '', + '
'].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 = ['
', + 'Enter a title for the new playlist:
', + '
', + 'Enter a description:
', + '
', + '', + '
'].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 = ['
', + 'Enter a title for the new playlist:
', + '
', + 'Enter a description:
', + '
', + '', + '', + '
'].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); +} diff --git a/zend/demos/Zend/Gdata/YouTubeVideoBrowser/index.php b/zend/demos/Zend/Gdata/YouTubeVideoBrowser/index.php new file mode 100755 index 0000000..607b905 --- /dev/null +++ b/zend/demos/Zend/Gdata/YouTubeVideoBrowser/index.php @@ -0,0 +1,278 @@ += 5.2.11 + * + * This sample is run from within a web browser. These files are required: + * index.php - the main logic, which interfaces with the YouTube API + * interface.html - the HTML to represent the web UI + * web_browser.css - the CSS to define the interface style + * web_browser.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. + */ + +/** + * @see Zend_Loader + */ +require_once 'Zend/Loader.php'; + +/** + * @see Zend_Gdata_YouTube + */ +Zend_Loader::loadClass('Zend_Gdata_YouTube'); + +/** + * 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; +} + +/** + * 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'; + $yt = new Zend_Gdata_YouTube(); + $ytQuery = $yt->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 $yt->getVideoFeed($ytQuery); +} + +/** + * 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) +{ + $yt = new Zend_Gdata_YouTube(); + $ytQuery = $yt->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 $yt->getVideoFeed($ytQuery); +} + +/** + * 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(); + echo ''; + } +} + +/** + * 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) +{ + $yt = new Zend_Gdata_YouTube(); + + $entry = $yt->getVideoEntry($videoId); + $videoTitle = $entry->mediaGroup->title; + $videoUrl = findFlashUrl($entry); + $relatedVideoFeed = getRelatedVideos($entry->getVideoId()); + $topRatedFeed = getTopRatedVideosByUser($entry->author[0]->name); + + print <<$videoTitle
+ + + + + +END; + echo '
'; + echoVideoMetadata($entry); + echo '
Related:
'; + echoThumbnails($relatedVideoFeed); + echo '
Top rated videos by user:
'; + echoThumbnails($topRatedFeed); +} + +/** + * Echo video metadata + * + * @param Zend_Gdata_YouTube_VideoEntry $entry The video entry + * @return void + */ +function echoVideoMetadata($entry) +{ + $title = $entry->mediaGroup->title; + $description = $entry->mediaGroup->description; + $authorUsername = $entry->author[0]->name; + $authorUrl = 'http://www.youtube.com/profile?user=' . $authorUsername; + $tags = $entry->mediaGroup->keywords; + $duration = $entry->mediaGroup->duration->seconds; + $watchPage = $entry->mediaGroup->player[0]->url; + $viewCount = $entry->statistics->viewCount; + $rating = $entry->rating->average; + $numRaters = $entry->rating->numRaters; + $flashUrl = findFlashUrl($entry); + print <<Title: ${title}
+ Description: ${description}
+ Author: ${authorUsername}
+ Tags: ${tags}
+ Duration: ${duration} seconds
+ View count: ${viewCount}
+ Rating: ${rating} (${numRaters} ratings)
+ Flash: ${flashUrl}
+ Watch page: ${watchPage}
+END; +} + +/** + * Echo the list of videos in the specified feed. + * + * @param Zend_Gdata_YouTube_VideoFeed $feed The video feed + * @return void + */ +function echoVideoList($feed) +{ + echo ''; + echo ''; + foreach ($feed as $entry) { + $videoId = $entry->getVideoId(); + $thumbnailUrl = $entry->mediaGroup->thumbnail[0]->url; + $videoTitle = $entry->mediaGroup->title; + $videoDescription = $entry->mediaGroup->description; + print << + + + +END; + } + echo '
+ ${videoTitle} +

${videoDescription}

+
'; +} + +/* + * The main controller logic of the YouTube video browser demonstration app. + */ +$queryType = isset($_POST['queryType']) ? $_POST['queryType'] : null; + +if ($queryType === null) { + /* display the entire interface */ + include 'interface.html'; +} else if ($queryType == 'show_video') { + /* display an individual video */ + if (array_key_exists('videoId', $_POST)) { + $videoId = $_POST['videoId']; + echoVideoPlayer($videoId); + } else if (array_key_exists('videoId', $_GET)) { + $videoId = $_GET['videoId']; + echoVideoPlayer($videoId); + } else { + echo 'No videoId found.'; + exit; + } +} else { + /* display a list of videos */ + $searchTerm = $_POST['searchTerm']; + $startIndex = $_POST['startIndex']; + $maxResults = $_POST['maxResults']; + + $yt = new Zend_Gdata_YouTube(); + $query = $yt->newVideoQuery(); + $query->setQuery($searchTerm); + $query->setStartIndex($startIndex); + $query->setMaxResults($maxResults); + + /* check for one of the standard feeds, or list from 'all' videos */ + switch ($queryType) { + case 'most_viewed': + $query->setFeedType('most viewed'); + $query->setTime('this_week'); + $feed = $yt->getVideoFeed($query); + break; + case 'most_recent': + $query->setFeedType('most recent'); + $feed = $yt->getVideoFeed($query); + break; + case 'recently_featured': + $query->setFeedType('recently featured'); + $feed = $yt->getVideoFeed($query); + break; + case 'top_rated': + $query->setFeedType('top rated'); + $query->setTime('this_week'); + $feed = $yt->getVideoFeed($query); + break; + case 'all': + $feed = $yt->getVideoFeed($query); + break; + default: + echo 'ERROR - unknown queryType - "' . $queryType . '"'; + break; + } + echoVideoList($feed); +} diff --git a/zend/demos/Zend/Gdata/YouTubeVideoBrowser/interface.html b/zend/demos/Zend/Gdata/YouTubeVideoBrowser/interface.html new file mode 100644 index 0000000..cfb7576 --- /dev/null +++ b/zend/demos/Zend/Gdata/YouTubeVideoBrowser/interface.html @@ -0,0 +1,79 @@ + + + + YouTube data API Video Browser in PHP + + + + +
+
+

YouTube data API Video Browser in PHP

+ +
+
+
+
+

Search YouTube:

+
+ + + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ + diff --git a/zend/demos/Zend/Gdata/YouTubeVideoBrowser/video_browser.css b/zend/demos/Zend/Gdata/YouTubeVideoBrowser/video_browser.css new file mode 100644 index 0000000..1984ed9 --- /dev/null +++ b/zend/demos/Zend/Gdata/YouTubeVideoBrowser/video_browser.css @@ -0,0 +1,152 @@ +body { + background-color: white; + color: black; + font-family: Arial, sans-serif; + font-size: small; + margin: 8px; + margin-top: 3px; +} + +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; +} + +/* "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 { + font-size: small; + margin: 0; + padding: 0; +} + +.videoList td { + padding-bottom: 5px; + padding-right: 5px; +} + +#titleBar { + border: 1px solid silver; + background-color: #e5ecf9; + font-size: large; + font-weight: bold; + 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; +} + +#mainSearchBox { + background-color: #e5ecf9; + border: 1px solid silver; + width: 250; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 10px; +} + +#searchResults { + width: 100%; +} + +#searchResultsListColumn { + float: left; + width: 47%; +} + +#searchResultsVideoColumn { + float: right; + width: 47%; +} diff --git a/zend/demos/Zend/Gdata/YouTubeVideoBrowser/video_browser.js b/zend/demos/Zend/Gdata/YouTubeVideoBrowser/video_browser.js new file mode 100644 index 0000000..3e91bcc --- /dev/null +++ b/zend/demos/Zend/Gdata/YouTubeVideoBrowser/video_browser.js @@ -0,0 +1,228 @@ +/** + * 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-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 using a PHP backend powered by the Zend_Gdata component + * of the Zend Framework. + */ + +/** + * provides namespacing for the YouTube Video Browser PHP version (ytvbp) + */ +var ytvbp = {}; + +/** + * maximum number of results to return for list of videos + * @type Number + */ +ytvbp.MAX_RESULTS_LIST = 5; + +/** + * navigation button id used to page to the previous page of + * results in the list of videos + * @type String + */ +ytvbp.PREVIOUS_PAGE_BUTTON = 'previousPageButton'; + +/** + * navigation button id used to page to the next page of + * results in the list of videos + * @type String + */ +ytvbp.NEXT_PAGE_BUTTON = 'nextPageButton'; + +/** + * container div id used to hold list of videos + * @type String + */ +ytvbp.VIDEO_LIST_CONTAINER_DIV = 'searchResultsVideoList'; + +/** + * container div id used to hold the video player + * @type String + */ +ytvbp.VIDEO_PLAYER_DIV = 'videoPlayer'; + +/** + * container div id used to hold the search box which displays when the page + * first loads + * @type String + */ +ytvbp.MAIN_SEARCH_CONTAINER_DIV = 'mainSearchBox'; + +/** + * 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 + */ +ytvbp.TOP_SEARCH_CONTAINER_DIV = 'searchBox'; + +/** + * the page number to use for the next page navigation button + * @type Number + */ +ytvbp.nextPage = 2; + +/** + * the page number to use for the previous page navigation button + * @type Number + */ +ytvbp.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 + */ +ytvbp.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 + */ +ytvbp.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} queryType The type of query to be done - either 'all' + * 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. + */ +ytvbp.listVideos = function(queryType, searchTerm, page) { + ytvbp.previousSearchTerm = searchTerm; + ytvbp.previousQueryType = queryType; + var maxResults = ytvbp.MAX_RESULTS_LIST; + var startIndex = (((page - 1) * ytvbp.MAX_RESULTS_LIST) + 1); + ytvbp.presentFeed(queryType, maxResults, startIndex, searchTerm); + ytvbp.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 + */ +ytvbp.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, true); + xmlhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + + xmlhr.onreadystatechange = function() { + var resultDiv = document.getElementById(resultDivName); + if (xmlhr.readyState == 1) { + resultDiv.innerHTML = 'Loading...'; + } 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 ytvbp.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 + */ +ytvbp.presentVideo = function(videoId) { + var params = 'queryType=show_video&videoId=' + videoId; + var filePath = 'index.php'; + ytvbp.sendRequest(filePath, params, ytvbp.VIDEO_PLAYER_DIV); +} + +/** + * Uses ytvbp.sendRequest to display a list of of YT videos. + * @param {String} queryType The name of a standard video feed or 'all' + * @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 + */ +ytvbp.presentFeed = function(queryType, maxResults, startIndex, searchTerm){ + var params = 'queryType=' + queryType + + '&maxResults=' + maxResults + + '&startIndex=' + startIndex + + '&searchTerm=' + searchTerm; + var filePath = 'index.php'; + ytvbp.sendRequest(filePath, params, ytvbp.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 + */ +ytvbp.updateNavigation = function(page) { + ytvbp.nextPage = page + 1; + ytvbp.previousPage = page - 1; + document.getElementById(ytvbp.NEXT_PAGE_BUTTON).style.display = 'inline'; + document.getElementById(ytvbp.PREVIOUS_PAGE_BUTTON).style.display = 'inline'; + if (ytvbp.previousPage < 1) { + document.getElementById(ytvbp.PREVIOUS_PAGE_BUTTON).disabled = true; + } else { + document.getElementById(ytvbp.PREVIOUS_PAGE_BUTTON).disabled = false; + } + document.getElementById(ytvbp.NEXT_PAGE_BUTTON).disabled = false; +}; + +/** + * Hides the main (large) search form and enables one that's in the + * title bar of the application. The main search form is only used + * for the first load. Subsequent searches should use the version in + * the title bar. + */ +ytvbp.hideMainSearch = function() { + document.getElementById(ytvbp.MAIN_SEARCH_CONTAINER_DIV).style.display = + 'none'; + document.getElementById(ytvbp.TOP_SEARCH_CONTAINER_DIV).style.display = + 'inline'; +}; + +/** + * 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} queryType The type of query being done - either 'all' + * for querying all videos, or the name of one of the standard feeds. + * @param {Node} searchTermInputElement The HTML input element for the input + * element. + */ +ytvbp.queryTypeChanged = function(queryType, searchTermInputElement) { + if (queryType != 'all') { + searchTermInputElement.value = ''; + } +}; -- cgit v1.2.3