]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - Zend/Gdata/YouTube.php
Release 6.5.0
[Github/sugarcrm.git] / Zend / Gdata / YouTube.php
1 <?php
2
3 /**
4  * Zend Framework
5  *
6  * LICENSE
7  *
8  * This source file is subject to the new BSD license that is bundled
9  * with this package in the file LICENSE.txt.
10  * It is also available through the world-wide-web at this URL:
11  * http://framework.zend.com/license/new-bsd
12  * If you did not receive a copy of the license and are unable to
13  * obtain it through the world-wide-web, please send an email
14  * to license@zend.com so we can send you a copy immediately.
15  *
16  * @category   Zend
17  * @package    Zend_Gdata
18  * @subpackage YouTube
19  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
20  * @license    http://framework.zend.com/license/new-bsd     New BSD License
21
22  */
23
24 /**
25  * @see Zend_Gdata_Media
26  */
27 require_once 'Zend/Gdata/Media.php';
28
29 /**
30  * @see Zend_Gdata_YouTube_VideoEntry
31  */
32 require_once 'Zend/Gdata/YouTube/VideoEntry.php';
33
34 /**
35  * @see Zend_Gdata_YouTube_VideoFeed
36  */
37 require_once 'Zend/Gdata/YouTube/VideoFeed.php';
38
39 /**
40  * @see Zend_Gdata_YouTube_CommentFeed
41  */
42 require_once 'Zend/Gdata/YouTube/CommentFeed.php';
43
44 /**
45  * @see Zend_Gdata_YouTube_PlaylistListFeed
46  */
47 require_once 'Zend/Gdata/YouTube/PlaylistListFeed.php';
48
49 /**
50  * @see Zend_Gdata_YouTube_SubscriptionFeed
51  */
52 require_once 'Zend/Gdata/YouTube/SubscriptionFeed.php';
53
54 /**
55  * @see Zend_Gdata_YouTube_ContactFeed
56  */
57 require_once 'Zend/Gdata/YouTube/ContactFeed.php';
58
59 /**
60  * @see Zend_Gdata_YouTube_PlaylistVideoFeed
61  */
62 require_once 'Zend/Gdata/YouTube/PlaylistVideoFeed.php';
63
64 /**
65  * @see Zend_Gdata_YouTube_ActivityFeed
66  */
67 require_once 'Zend/Gdata/YouTube/ActivityFeed.php';
68
69 /**
70  * @see Zend_Gdata_YouTube_InboxFeed
71  */
72 require_once 'Zend/Gdata/YouTube/InboxFeed.php';
73
74
75 /**
76  * Service class for interacting with the YouTube Data API.
77  * @link http://code.google.com/apis/youtube/
78  *
79  * @category   Zend
80  * @package    Zend_Gdata
81  * @subpackage YouTube
82  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
83  * @license    http://framework.zend.com/license/new-bsd     New BSD License
84  */
85 class Zend_Gdata_YouTube extends Zend_Gdata_Media
86 {
87
88     const AUTH_SERVICE_NAME = 'youtube';
89     const CLIENTLOGIN_URL = 'https://www.google.com/youtube/accounts/ClientLogin';
90
91     const STANDARD_TOP_RATED_URI = 'http://gdata.youtube.com/feeds/api/standardfeeds/top_rated';
92     const STANDARD_MOST_VIEWED_URI = 'http://gdata.youtube.com/feeds/api/standardfeeds/most_viewed';
93     const STANDARD_RECENTLY_FEATURED_URI = 'http://gdata.youtube.com/feeds/api/standardfeeds/recently_featured';
94     const STANDARD_WATCH_ON_MOBILE_URI = 'http://gdata.youtube.com/feeds/api/standardfeeds/watch_on_mobile';
95
96     const STANDARD_TOP_RATED_URI_V2 =
97         'http://gdata.youtube.com/feeds/api/standardfeeds/top_rated';
98     const STANDARD_MOST_VIEWED_URI_V2 =
99         'http://gdata.youtube.com/feeds/api/standardfeeds/most_viewed';
100     const STANDARD_RECENTLY_FEATURED_URI_V2 =
101         'http://gdata.youtube.com/feeds/api/standardfeeds/recently_featured';
102     const STANDARD_WATCH_ON_MOBILE_URI_V2 =
103         'http://gdata.youtube.com/feeds/api/standardfeeds/watch_on_mobile';
104
105     const USER_URI = 'http://gdata.youtube.com/feeds/api/users';
106     const VIDEO_URI = 'http://gdata.youtube.com/feeds/api/videos';
107     const PLAYLIST_REL = 'http://gdata.youtube.com/schemas/2007#playlist';
108     const USER_UPLOADS_REL = 'http://gdata.youtube.com/schemas/2007#user.uploads';
109     const USER_PLAYLISTS_REL = 'http://gdata.youtube.com/schemas/2007#user.playlists';
110     const USER_SUBSCRIPTIONS_REL = 'http://gdata.youtube.com/schemas/2007#user.subscriptions';
111     const USER_CONTACTS_REL = 'http://gdata.youtube.com/schemas/2007#user.contacts';
112     const USER_FAVORITES_REL = 'http://gdata.youtube.com/schemas/2007#user.favorites';
113     const VIDEO_RESPONSES_REL = 'http://gdata.youtube.com/schemas/2007#video.responses';
114     const VIDEO_RATINGS_REL = 'http://gdata.youtube.com/schemas/2007#video.ratings';
115     const VIDEO_COMPLAINTS_REL = 'http://gdata.youtube.com/schemas/2007#video.complaints';
116     const ACTIVITY_FEED_URI = 'http://gdata.youtube.com/feeds/api/events';
117     const FRIEND_ACTIVITY_FEED_URI =
118         'http://gdata.youtube.com/feeds/api/users/default/friendsactivity';
119
120     /**
121      * The URI of the in-reply-to schema for comments in reply to
122      * other comments.
123      *
124      * @var string
125      */
126      const IN_REPLY_TO_SCHEME =
127          'http://gdata.youtube.com/schemas/2007#in-reply-to';
128
129     /**
130      * The URI of the inbox feed for the currently authenticated user.
131      *
132      * @var string
133      */
134     const INBOX_FEED_URI =
135         'http://gdata.youtube.com/feeds/api/users/default/inbox';
136
137     /**
138      * The maximum number of users for which activity can be requested for,
139      * as enforced by the API.
140      *
141      * @var integer
142      */
143     const ACTIVITY_FEED_MAX_USERS = 20;
144
145     /**
146      * The suffix for a feed of favorites.
147      *
148      * @var string
149      */
150     const FAVORITES_URI_SUFFIX = 'favorites';
151
152     /**
153      * The suffix for the user's upload feed.
154      *
155      * @var string
156      */
157     const UPLOADS_URI_SUFFIX = 'uploads';
158
159     /**
160      * The suffix for a feed of video responses.
161      *
162      * @var string
163      */
164     const RESPONSES_URI_SUFFIX = 'responses';
165
166     /**
167      * The suffix for a feed of related videos.
168      *
169      * @var string
170      */
171     const RELATED_URI_SUFFIX = 'related';
172
173     /**
174      * The suffix for a feed of messages (inbox entries).
175      *
176      * @var string
177      */
178     const INBOX_URI_SUFFIX = 'inbox';
179
180     /**
181      * Namespaces used for Zend_Gdata_YouTube
182      *
183      * @var array
184      */
185     public static $namespaces = array(
186         array('yt', 'http://gdata.youtube.com/schemas/2007', 1, 0),
187         array('georss', 'http://www.georss.org/georss', 1, 0),
188         array('gml', 'http://www.opengis.net/gml', 1, 0),
189         array('media', 'http://search.yahoo.com/mrss/', 1, 0)
190     );
191
192     /**
193      * Create Zend_Gdata_YouTube object
194      *
195      * @param Zend_Http_Client $client (optional) The HTTP client to use when
196      *          when communicating with the Google servers.
197      * @param string $applicationId The identity of the app in the form of
198      *        Company-AppName-Version
199      * @param string $clientId The clientId issued by the YouTube dashboard
200      * @param string $developerKey The developerKey issued by the YouTube dashboard
201      */
202     public function __construct($client = null,
203         $applicationId = 'MyCompany-MyApp-1.0', $clientId = null,
204         $developerKey = null)
205     {
206         $this->registerPackage('Zend_Gdata_YouTube');
207         $this->registerPackage('Zend_Gdata_YouTube_Extension');
208         $this->registerPackage('Zend_Gdata_Media');
209         $this->registerPackage('Zend_Gdata_Media_Extension');
210
211         // NOTE This constructor no longer calls the parent constructor
212         $this->setHttpClient($client, $applicationId, $clientId, $developerKey);
213     }
214
215     /**
216      * Set the Zend_Http_Client object used for communication
217      *
218      * @param Zend_Http_Client $client The client to use for communication
219      * @throws Zend_Gdata_App_HttpException
220      * @return Zend_Gdata_App Provides a fluent interface
221      */
222     public function setHttpClient($client,
223         $applicationId = 'MyCompany-MyApp-1.0', $clientId = null,
224         $developerKey = null)
225     {
226         if ($client === null) {
227             $client = new Zend_Http_Client();
228         }
229         if (!$client instanceof Zend_Http_Client) {
230             require_once 'Zend/Gdata/App/HttpException.php';
231             throw new Zend_Gdata_App_HttpException(
232                 'Argument is not an instance of Zend_Http_Client.');
233         }
234
235         if ($clientId != null) {
236             $client->setHeaders('X-GData-Client', $clientId);
237         }
238
239         if ($developerKey != null) {
240             $client->setHeaders('X-GData-Key', 'key='. $developerKey);
241         }
242
243         return parent::setHttpClient($client, $applicationId);
244     }
245
246     /**
247      * Retrieves a feed of videos.
248      *
249      * @param mixed $location (optional) The URL to query or a
250      *         Zend_Gdata_Query object from which a URL can be determined
251      * @return Zend_Gdata_YouTube_VideoFeed The feed of videos found at the
252      *         specified URL.
253      */
254     public function getVideoFeed($location = null)
255     {
256         if ($location == null) {
257             $uri = self::VIDEO_URI;
258         } else if ($location instanceof Zend_Gdata_Query) {
259             $uri = $location->getQueryUrl();
260         } else {
261             $uri = $location;
262         }
263         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
264     }
265
266     /**
267      * Retrieves a specific video entry.
268      *
269      * @param mixed $videoId The ID of the video to retrieve.
270      * @param mixed $location (optional) The URL to query or a
271      *         Zend_Gdata_Query object from which a URL can be determined.
272      * @param boolean $fullEntry (optional) Retrieve the full metadata for the
273      *         entry. Only possible if entry belongs to currently authenticated
274      *         user. An exception will be thrown otherwise.
275      * @throws Zend_Gdata_App_HttpException
276      * @return Zend_Gdata_YouTube_VideoEntry The video entry found at the
277      *         specified URL.
278      */
279     public function getVideoEntry($videoId = null, $location = null,
280         $fullEntry = false)
281     {
282         if ($videoId !== null) {
283             if ($fullEntry) {
284                 return $this->getFullVideoEntry($videoId);
285             } else {
286                 $uri = self::VIDEO_URI . "/" . $videoId;
287             }
288         } else if ($location instanceof Zend_Gdata_Query) {
289             $uri = $location->getQueryUrl();
290         } else {
291             $uri = $location;
292         }
293         return parent::getEntry($uri, 'Zend_Gdata_YouTube_VideoEntry');
294     }
295
296     /**
297      * Retrieves a video entry from the user's upload feed.
298      *
299      * @param mixed $videoID The ID of the video to retrieve.
300      * @throws Zend_Gdata_App_HttpException
301      * @return Zend_Gdata_YouTube_VideoEntry|null The video entry to be
302      *          retrieved, or null if it was not found or the user requesting it
303      *          did not have the appropriate permissions.
304      */
305     public function getFullVideoEntry($videoId)
306     {
307         $uri = self::USER_URI . "/default/" .
308             self::UPLOADS_URI_SUFFIX . "/$videoId";
309         return parent::getEntry($uri, 'Zend_Gdata_YouTube_VideoEntry');
310     }
311
312     /**
313      * Retrieves a feed of videos related to the specified video ID.
314      *
315      * @param string $videoId The videoId of interest
316      * @param mixed $location (optional) The URL to query or a
317      *         Zend_Gdata_Query object from which a URL can be determined
318      * @return Zend_Gdata_YouTube_VideoFeed The feed of videos found at the
319      *         specified URL.
320      */
321     public function getRelatedVideoFeed($videoId = null, $location = null)
322     {
323         if ($videoId !== null) {
324             $uri = self::VIDEO_URI . "/" . $videoId . "/" .
325                 self::RELATED_URI_SUFFIX;
326         } else if ($location instanceof Zend_Gdata_Query) {
327             $uri = $location->getQueryUrl();
328         } else {
329             $uri = $location;
330         }
331         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
332     }
333
334     /**
335      * Retrieves a feed of video responses related to the specified video ID.
336      *
337      * @param string $videoId The videoId of interest
338      * @param mixed $location (optional) The URL to query or a
339      *         Zend_Gdata_Query object from which a URL can be determined
340      * @return Zend_Gdata_YouTube_VideoFeed The feed of videos found at the
341      *         specified URL.
342      */
343     public function getVideoResponseFeed($videoId = null, $location = null)
344     {
345         if ($videoId !== null) {
346             $uri = self::VIDEO_URI . "/" . $videoId . "/" .
347                 self::RESPONSES_URI_SUFFIX;
348         } else if ($location instanceof Zend_Gdata_Query) {
349             $uri = $location->getQueryUrl();
350         } else {
351             $uri = $location;
352         }
353         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
354     }
355
356     /**
357      * Retrieves a feed of comments related to the specified video ID.
358      *
359      * @param string $videoId The videoId of interest
360      * @param mixed $location (optional) The URL to query or a
361      *         Zend_Gdata_Query object from which a URL can be determined
362      * @return Zend_Gdata_YouTube_CommentFeed The feed of videos found at the
363      *         specified URL.
364      */
365     public function getVideoCommentFeed($videoId = null, $location = null)
366     {
367         if ($videoId !== null) {
368             $uri = self::VIDEO_URI . "/" . $videoId . "/comments";
369         } else if ($location instanceof Zend_Gdata_Query) {
370             $uri = $location->getQueryUrl();
371         } else {
372             $uri = $location;
373         }
374         return parent::getFeed($uri, 'Zend_Gdata_YouTube_CommentFeed');
375     }
376
377     /**
378      * Retrieves a feed of comments related to the specified video ID.
379      *
380      * @param mixed $location (optional) The URL to query or a
381      *         Zend_Gdata_Query object from which a URL can be determined
382      * @return Zend_Gdata_YouTube_CommentFeed The feed of videos found at the
383      *         specified URL.
384      */
385     public function getTopRatedVideoFeed($location = null)
386     {
387         $standardFeedUri = self::STANDARD_TOP_RATED_URI;
388
389         if ($this->getMajorProtocolVersion() == 2) {
390             $standardFeedUri = self::STANDARD_TOP_RATED_URI_V2;
391         }
392
393         if ($location == null) {
394             $uri = $standardFeedUri;
395         } else if ($location instanceof Zend_Gdata_Query) {
396             if ($location instanceof Zend_Gdata_YouTube_VideoQuery) {
397                 if (!isset($location->url)) {
398                     $location->setFeedType('top rated');
399                 }
400             }
401             $uri = $location->getQueryUrl();
402         } else {
403             $uri = $location;
404         }
405         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
406     }
407
408
409     /**
410      * Retrieves a feed of the most viewed videos.
411      *
412      * @param mixed $location (optional) The URL to query or a
413      *         Zend_Gdata_Query object from which a URL can be determined
414      * @return Zend_Gdata_YouTube_VideoFeed The feed of videos found at the
415      *         specified URL.
416      */
417     public function getMostViewedVideoFeed($location = null)
418     {
419         $standardFeedUri = self::STANDARD_MOST_VIEWED_URI;
420
421         if ($this->getMajorProtocolVersion() == 2) {
422             $standardFeedUri = self::STANDARD_MOST_VIEWED_URI_V2;
423         }
424
425         if ($location == null) {
426             $uri = $standardFeedUri;
427         } else if ($location instanceof Zend_Gdata_Query) {
428             if ($location instanceof Zend_Gdata_YouTube_VideoQuery) {
429                 if (!isset($location->url)) {
430                     $location->setFeedType('most viewed');
431                 }
432             }
433             $uri = $location->getQueryUrl();
434         } else {
435             $uri = $location;
436         }
437         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
438     }
439
440     /**
441      * Retrieves a feed of recently featured videos.
442      *
443      * @param mixed $location (optional) The URL to query or a
444      *         Zend_Gdata_Query object from which a URL can be determined
445      * @return Zend_Gdata_YouTube_VideoFeed The feed of videos found at the
446      *         specified URL.
447      */
448     public function getRecentlyFeaturedVideoFeed($location = null)
449     {
450         $standardFeedUri = self::STANDARD_RECENTLY_FEATURED_URI;
451
452         if ($this->getMajorProtocolVersion() == 2) {
453             $standardFeedUri = self::STANDARD_RECENTLY_FEATURED_URI_V2;
454         }
455
456         if ($location == null) {
457             $uri = $standardFeedUri;
458         } else if ($location instanceof Zend_Gdata_Query) {
459             if ($location instanceof Zend_Gdata_YouTube_VideoQuery) {
460                 if (!isset($location->url)) {
461                     $location->setFeedType('recently featured');
462                 }
463             }
464             $uri = $location->getQueryUrl();
465         } else {
466             $uri = $location;
467         }
468         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
469     }
470
471     /**
472      * Retrieves a feed of videos recently featured for mobile devices.
473      * These videos will have RTSP links in the $entry->mediaGroup->content
474      *
475      * @param mixed $location (optional) The URL to query or a
476      *         Zend_Gdata_Query object from which a URL can be determined
477      * @return Zend_Gdata_YouTube_VideoFeed The feed of videos found at the
478      *         specified URL.
479      */
480     public function getWatchOnMobileVideoFeed($location = null)
481     {
482         $standardFeedUri = self::STANDARD_WATCH_ON_MOBILE_URI;
483
484         if ($this->getMajorProtocolVersion() == 2) {
485             $standardFeedUri = self::STANDARD_WATCH_ON_MOBILE_URI_V2;
486         }
487
488         if ($location == null) {
489             $uri = $standardFeedUri;
490         } else if ($location instanceof Zend_Gdata_Query) {
491             if ($location instanceof Zend_Gdata_YouTube_VideoQuery) {
492                 if (!isset($location->url)) {
493                     $location->setFeedType('watch on mobile');
494                 }
495             }
496             $uri = $location->getQueryUrl();
497         } else {
498             $uri = $location;
499         }
500         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
501     }
502
503     /**
504      * Retrieves a feed which lists a user's playlist
505      *
506      * @param string $user (optional) The username of interest
507      * @param mixed $location (optional) The URL to query or a
508      *         Zend_Gdata_Query object from which a URL can be determined
509      * @return Zend_Gdata_YouTube_PlaylistListFeed The feed of playlists
510      */
511     public function getPlaylistListFeed($user = null, $location = null)
512     {
513         if ($user !== null) {
514             $uri = self::USER_URI . '/' . $user . '/playlists';
515         } else if ($location instanceof Zend_Gdata_Query) {
516             $uri = $location->getQueryUrl();
517         } else {
518             $uri = $location;
519         }
520         return parent::getFeed($uri, 'Zend_Gdata_YouTube_PlaylistListFeed');
521     }
522
523     /**
524      * Retrieves a feed of videos in a particular playlist
525      *
526      * @param mixed $location (optional) The URL to query or a
527      *         Zend_Gdata_Query object from which a URL can be determined
528      * @return Zend_Gdata_YouTube_PlaylistVideoFeed The feed of videos found at
529      *         the specified URL.
530      */
531     public function getPlaylistVideoFeed($location)
532     {
533         if ($location instanceof Zend_Gdata_Query) {
534             $uri = $location->getQueryUrl();
535         } else {
536             $uri = $location;
537         }
538         return parent::getFeed($uri, 'Zend_Gdata_YouTube_PlaylistVideoFeed');
539     }
540
541     /**
542      * Retrieves a feed of a user's subscriptions
543      *
544      * @param string $user (optional) The username of interest
545      * @param mixed $location (optional) The URL to query or a
546      *         Zend_Gdata_Query object from which a URL can be determined
547      * @return Zend_Gdata_YouTube_SubscriptionListFeed The feed of subscriptions
548      */
549     public function getSubscriptionFeed($user = null, $location = null)
550     {
551         if ($user !== null) {
552             $uri = self::USER_URI . '/' . $user . '/subscriptions';
553         } else if ($location instanceof Zend_Gdata_Query) {
554             $uri = $location->getQueryUrl();
555         } else {
556             $uri = $location;
557         }
558         return parent::getFeed($uri, 'Zend_Gdata_YouTube_SubscriptionFeed');
559     }
560
561     /**
562      * Retrieves a feed of a user's contacts
563      *
564      * @param string $user (optional) The username of interest
565      * @param mixed $location (optional) The URL to query or a
566      *         Zend_Gdata_Query object from which a URL can be determined
567      * @return Zend_Gdata_YouTube_ContactFeed The feed of contacts
568      */
569     public function getContactFeed($user = null, $location = null)
570     {
571         if ($user !== null) {
572             $uri = self::USER_URI . '/' . $user . '/contacts';
573         } else if ($location instanceof Zend_Gdata_Query) {
574             $uri = $location->getQueryUrl();
575         } else {
576             $uri = $location;
577         }
578         return parent::getFeed($uri, 'Zend_Gdata_YouTube_ContactFeed');
579     }
580
581     /**
582      * Retrieves a user's uploads
583      *
584      * @param string $user (optional) The username of interest
585      * @param mixed $location (optional) The URL to query or a
586      *         Zend_Gdata_Query object from which a URL can be determined
587      * @return Zend_Gdata_YouTube_VideoFeed The videos uploaded by the user
588      */
589     public function getUserUploads($user = null, $location = null)
590     {
591         if ($user !== null) {
592             $uri = self::USER_URI . '/' . $user . '/' .
593                    self::UPLOADS_URI_SUFFIX;
594         } else if ($location instanceof Zend_Gdata_Query) {
595             $uri = $location->getQueryUrl();
596         } else {
597             $uri = $location;
598         }
599         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
600     }
601
602     /**
603      * Retrieves a user's favorites
604      *
605      * @param string $user (optional) The username of interest
606      * @param mixed $location (optional) The URL to query or a
607      *         Zend_Gdata_Query object from which a URL can be determined
608      * @return Zend_Gdata_YouTube_VideoFeed The videos favorited by the user
609      */
610     public function getUserFavorites($user = null, $location = null)
611     {
612         if ($user !== null) {
613             $uri = self::USER_URI . '/' . $user . '/' .
614                    self::FAVORITES_URI_SUFFIX;
615         } else if ($location instanceof Zend_Gdata_Query) {
616             $uri = $location->getQueryUrl();
617         } else {
618             $uri = $location;
619         }
620         return parent::getFeed($uri, 'Zend_Gdata_YouTube_VideoFeed');
621     }
622
623     /**
624      * Retrieves a user's profile as an entry
625      *
626      * @param string $user (optional) The username of interest
627      * @param mixed $location (optional) The URL to query or a
628      *         Zend_Gdata_Query object from which a URL can be determined
629      * @return Zend_Gdata_YouTube_UserProfileEntry The user profile entry
630      */
631     public function getUserProfile($user = null, $location = null)
632     {
633         if ($user !== null) {
634             $uri = self::USER_URI . '/' . $user;
635         } else if ($location instanceof Zend_Gdata_Query) {
636             $uri = $location->getQueryUrl();
637         } else {
638             $uri = $location;
639         }
640         return parent::getEntry($uri, 'Zend_Gdata_YouTube_UserProfileEntry');
641     }
642
643     /**
644      * Helper function for parsing a YouTube token response
645      *
646      * @param string $response The service response
647      * @throws Zend_Gdata_App_Exception
648      * @return array An array containing the token and URL
649      */
650     public static function parseFormUploadTokenResponse($response)
651     {
652         // Load the feed as an XML DOMDocument object
653         @ini_set('track_errors', 1);
654         $doc = new DOMDocument();
655         $success = @$doc->loadXML($response);
656         @ini_restore('track_errors');
657
658         if (!$success) {
659             require_once 'Zend/Gdata/App/Exception.php';
660             throw new Zend_Gdata_App_Exception(
661                 "Zend_Gdata_YouTube::parseFormUploadTokenResponse - " .
662                 "DOMDocument cannot parse XML: $php_errormsg");
663         }
664         $responseElement = $doc->getElementsByTagName('response')->item(0);
665
666         $urlText = null;
667         $tokenText = null;
668         if ($responseElement != null) {
669             $urlElement =
670                 $responseElement->getElementsByTagName('url')->item(0);
671             $tokenElement =
672                 $responseElement->getElementsByTagName('token')->item(0);
673
674             if ($urlElement && $urlElement->hasChildNodes() &&
675                 $tokenElement && $tokenElement->hasChildNodes()) {
676
677                 $urlText = $urlElement->firstChild->nodeValue;
678                 $tokenText = $tokenElement->firstChild->nodeValue;
679             }
680         }
681
682         if ($tokenText != null && $urlText != null) {
683             return array('token' => $tokenText, 'url' => $urlText);
684         } else {
685             require_once 'Zend/Gdata/App/Exception.php';
686             throw new Zend_Gdata_App_Exception(
687                 'Form upload token not found in response');
688         }
689     }
690
691     /**
692      * Retrieves a YouTube token
693      *
694      * @param Zend_Gdata_YouTube_VideoEntry $videoEntry The video entry
695      * @param string $url The location as a string URL
696      * @throws Zend_Gdata_App_Exception
697      * @return array An array containing a token and URL
698      */
699     public function getFormUploadToken($videoEntry,
700         $url='http://gdata.youtube.com/action/GetUploadToken')
701     {
702         if ($url != null && is_string($url)) {
703             // $response is a Zend_Http_response object
704             $response = $this->post($videoEntry, $url);
705             return self::parseFormUploadTokenResponse($response->getBody());
706         } else {
707             require_once 'Zend/Gdata/App/Exception.php';
708             throw new Zend_Gdata_App_Exception(
709                 'Url must be provided as a string URL');
710         }
711     }
712
713     /**
714      * Retrieves the activity feed for users
715      *
716      * @param mixed $usernames A string identifying the usernames for which to
717      *              retrieve activity for. This can also be a Zend_Gdata_Query
718      *              object from which a URL can be determined.
719      * @throws Zend_Gdata_App_VersionException if using version less than 2.
720      * @return Zend_Gdata_YouTube_ActivityFeed
721      */
722     public function getActivityForUser($username)
723     {
724         if ($this->getMajorProtocolVersion() == 1) {
725             require_once 'Zend/Gdata/App/VersionException.php';
726             throw new Zend_Gdata_App_VersionException('User activity feeds ' .
727                 'are not available in API version 1.');
728         }
729
730         $uri = null;
731         if ($username instanceof Zend_Gdata_Query) {
732             $uri = $username->getQueryUrl();
733         } else {
734             if (count(explode(',', $username)) >
735                 self::ACTIVITY_FEED_MAX_USERS) {
736                 require_once 'Zend/Gdata/App/InvalidArgumentException.php';
737                 throw new Zend_Gdata_App_InvalidArgumentException(
738                     'Activity feed can only retrieve for activity for up to ' .
739                     self::ACTIVITY_FEED_MAX_USERS .  ' users per request');
740             }
741             $uri = self::ACTIVITY_FEED_URI . '?author=' . $username;
742         }
743
744         return parent::getFeed($uri, 'Zend_Gdata_YouTube_ActivityFeed');
745     }
746
747     /**
748      * Retrieve the activity of the currently authenticated users friend.
749      *
750      * @throws Zend_Gdata_App_Exception if not logged in.
751      * @return Zend_Gdata_YouTube_ActivityFeed
752      */
753     public function getFriendActivityForCurrentUser()
754     {
755         if (!$this->isAuthenticated()) {
756             require_once 'Zend/Gdata/App/Exception.php';
757             throw new Zend_Gdata_App_Exception('You must be authenticated to ' .
758                 'use the getFriendActivityForCurrentUser function in Zend_' .
759                 'Gdata_YouTube.');
760         }
761         return parent::getFeed(self::FRIEND_ACTIVITY_FEED_URI,
762             'Zend_Gdata_YouTube_ActivityFeed');
763     }
764
765     /**
766      * Retrieve a feed of messages in the currently authenticated user's inbox.
767      *
768      * @throws Zend_Gdata_App_Exception if not logged in.
769      * @return Zend_Gdata_YouTube_InboxFeed|null
770      */
771     public function getInboxFeedForCurrentUser()
772     {
773         if (!$this->isAuthenticated()) {
774             require_once 'Zend/Gdata/App/Exception.php';
775             throw new Zend_Gdata_App_Exception('You must be authenticated to ' .
776                 'use the getInboxFeedForCurrentUser function in Zend_' .
777                 'Gdata_YouTube.');
778         }
779
780         return parent::getFeed(self::INBOX_FEED_URI,
781             'Zend_Gdata_YouTube_InboxFeed');
782     }
783
784     /**
785      * Send a video message.
786      *
787      * Note: Either a Zend_Gdata_YouTube_VideoEntry or a valid video ID must
788      * be provided.
789      *
790      * @param string $body The body of the message
791      * @param Zend_Gdata_YouTube_VideoEntry (optional) The video entry to send
792      * @param string $videoId The id of the video to send
793      * @param string $recipientUserName The username of the recipient
794      * @throws Zend_Gdata_App_InvalidArgumentException if no valid
795      *         Zend_Gdata_YouTube_VideoEntry or videoId were provided
796      * @return Zend_Gdata_YouTube_InboxEntry|null The
797      *         Zend_Gdata_YouTube_Inbox_Entry representing the sent message.
798      *
799      */
800     public function sendVideoMessage($body, $videoEntry = null,
801         $videoId = null, $recipientUserName)
802     {
803         if (!$videoId && !$videoEntry) {
804             require_once 'Zend/Gdata/App/InvalidArgumentException.php';
805             throw new Zend_Gdata_App_InvalidArgumentException(
806                 'Expecting either a valid videoID or a videoEntry object in ' .
807                 'Zend_Gdata_YouTube->sendVideoMessage().');
808         }
809
810         $messageEntry = new Zend_Gdata_YouTube_InboxEntry();
811
812         if ($this->getMajorProtocolVersion() == null ||
813             $this->getMajorProtocolVersion() == 1) {
814
815             if (!$videoId) {
816                 $videoId = $videoEntry->getVideoId();
817             } elseif (strlen($videoId) < 12) {
818                 //Append the full URI
819                 $videoId = self::VIDEO_URI . '/' . $videoId;
820             }
821
822             $messageEntry->setId($this->newId($videoId));
823             // TODO there seems to be a bug where v1 inbox entries dont
824             // retain their description...
825             $messageEntry->setDescription(
826                 new Zend_Gdata_YouTube_Extension_Description($body));
827
828         } else {
829             if (!$videoId) {
830                 $videoId = $videoEntry->getVideoId();
831                 $videoId = substr($videoId, strrpos($videoId, ':'));
832             }
833             $messageEntry->setId($this->newId($videoId));
834             $messageEntry->setSummary($this->newSummary($body));
835         }
836
837         $insertUrl = 'http://gdata.youtube.com/feeds/api/users/' .
838             $recipientUserName . '/inbox';
839         $response = $this->insertEntry($messageEntry, $insertUrl,
840             'Zend_Gdata_YouTube_InboxEntry');
841         return $response;
842     }
843
844     /**
845      * Post a comment in reply to an existing comment
846      *
847      * @param $commentEntry Zend_Gdata_YouTube_CommentEntry The comment entry
848      *        to reply to
849      * @param $commentText string The text of the comment to post
850      * @return A Zend_Gdata_YouTube_CommentEntry representing the posted
851      *         comment
852      */
853     public function replyToCommentEntry($commentEntry, $commentText)
854     {
855         $newComment = $this->newCommentEntry();
856         $newComment->content = $this->newContent()->setText($commentText);
857         $commentId = $commentEntry->getId();
858         $commentIdArray = explode(':', $commentId);
859
860         // create a new link element
861         $inReplyToLinkHref = self::VIDEO_URI . '/' . $commentIdArray[3] .
862             '/comments/' . $commentIdArray[5];
863         $inReplyToLink = $this->newLink($inReplyToLinkHref,
864             self::IN_REPLY_TO_SCHEME, $type="application/atom+xml");
865         $links = $newComment->getLink();
866         $links[] = $inReplyToLink;
867         $newComment->setLink($links);
868         $commentFeedPostUrl = self::VIDEO_URI . '/' . $commentIdArray[3] .
869             '/comments';
870         return $this->insertEntry($newComment,
871             $commentFeedPostUrl, 'Zend_Gdata_YouTube_CommentEntry');
872     }
873
874 }