From cf79f1e5a22602e1f661298b98d8ac862c56f18a Mon Sep 17 00:00:00 2001 From: Jim Date: Fri, 18 May 2012 15:25:09 -0400 Subject: [PATCH 1/8] Changed direct upload to use chunked uploading and avoid potential memory issues with large videos --- libraries/Youtube.php | 71 +++++++++++++++++++++++++++++++------------ spark.info | 2 +- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/libraries/Youtube.php b/libraries/Youtube.php index d3ec59f..5cefbd5 100644 --- a/libraries/Youtube.php +++ b/libraries/Youtube.php @@ -458,57 +458,88 @@ private function _data_request($uri, $metadata, $method = 'POST') * @param string $path The path on your server to the video to upload. * @param string $contenttype The mime-type of the video to upload. * @param string $metadata XML information about the video to upload. + * @param int (optional) $filesize the size of the video to upload in bytes. The library will calculate it if not set. * @param string (optional) $user the user name whose account this video will go to. Defaults to the authenticated user. **/ - public function directUpload($path, $contenttype, $metadata, $user = 'default') + public function directUpload($path, $contenttype, $metadata, $filesize = false, $user = 'default') { if($this->_access !== false) { $uri = "/{$this->_uris['USER_URI']}/{$user}/uploads"; $header = "POST {$uri} HTTP/".self::HTTP_1.self::LINE_END; //We use a special host for direct uploads. - $host = "uploads.gdata.youtube.com"; - $url = "http://".$host.$uri; + $host = 'uploads.gdata.youtube.com'; + $url = "http://{$host}{$uri}"; $extra = "GData-Version: 2.0".self::LINE_END; //Add the file name to the slug parameter. $extra .= "Slug: ".basename($path).self::LINE_END; - //Create a random boundry string. + //Create a random boundary string. $this->CI->load->helper('string'); - $boundry = random_string(); - $extra .= "Content-Type: multipart/related; boundary=\"{$boundry}\"".self::LINE_END; - + $boundary = random_string(); + $extra .= "Content-Type: multipart/related; boundary=\"{$boundary}\"".self::LINE_END; + //Build out the data portion of the request - $data = "--".$boundry.self::LINE_END; + $data = "--{$boundary}".self::LINE_END; $data .= "Content-Type: application/atom+xml; charset=UTF-8".self::LINE_END.self::LINE_END; $data .= $metadata.self::LINE_END; - $data .= "--".$boundry.self::LINE_END; + $data .= "--{$boundary}".self::LINE_END; $data .= "Content-Type: ".$contenttype.self::LINE_END; $data .= "Content-Transfer-Encoding: binary".self::LINE_END.self::LINE_END; - $data .= file_get_contents($path).self::LINE_END; - $data .= "--{$boundry}--".self::LINE_END; - + + $end = self::LINE_END."--{$boundary}--".self::LINE_END; + + //If file size is not set then calculate it + //NOTE: This may cause memory problems for large videos + if($filesize === false)$filesize = filesize($path); + + $length = strlen($data) + intval($filesize) + strlen($end); + //Calculate the size of the data portion. - $extra .= "Content-Length: ".strlen($data).self::LINE_END.self::LINE_END; + $extra .= "Content-Length: {$length}".self::LINE_END.self::LINE_END; $this->_header['Host'] = $host;//Swap the default host - $fullrequest = $this->_build_header($url, $header, $extra, 'POST'); + $start = $this->_build_header($url, $header, $extra, 'POST'); $this->_header['Host'] = self::HOST;//Revert the default host. - $fullrequest .= $data; - + $start .= $data; + $handle = null; //Connect to the special upload host $handle = $this->_connect($host); - - $this->_write($handle, $fullrequest); + //Write the request header + $this->_write($handle, $start); + //Write the file data + $this->_write_file($handle, $path); + //Write the ending + $this->_write($handle, $end); + $output = $this->_read($handle); - + fclose($handle); $handle = null; - + return $output; } return false; } + /** + * Writes a file specified by path to the stream specified by the handle. + * The file is written in chunks specified by the chunk size to decrease + * the potential memory footprint. + * + * @param stream $handle Handle to the stream to write to + * @param string $path Path of the file to read from + * @param int $chunksize Size of each chunk that is read from the file. + */ + private function _write_file($handle, $path, $chunksize = 8192) + { + $filehandle = fopen($path, 'r'); + while(!feof($filehandle)) + fwrite($handle, fread($filehandle, $chunksize)); + + fclose($filehandle); + $filehandle = null; + } + /** * Makes a data request for a youtube upload token. diff --git a/spark.info b/spark.info index dfd0cc8..4d00c59 100644 --- a/spark.info +++ b/spark.info @@ -1,4 +1,4 @@ name: youtube -version: 1.0.9 +version: 1.1.0 compatibility: 2.0.3 tags: ["youtube", "youtube api", "google oauth", "api"] From 2b812aa957e89df792cc9b5c04cac7fd4edcf4e7 Mon Sep 17 00:00:00 2001 From: Jim Date: Fri, 1 Jun 2012 12:19:48 -0400 Subject: [PATCH 2/8] Updated a few calls to allow parameter passing. Also changed library constructors to comply with current CI standards --- libraries/Google_oauth.php | 2 +- libraries/Youtube.php | 10 +++++----- spark.info | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/Google_oauth.php b/libraries/Google_oauth.php index a1616da..8e48e8a 100644 --- a/libraries/Google_oauth.php +++ b/libraries/Google_oauth.php @@ -59,7 +59,7 @@ class Google_oauth * * @param array $params */ - public function google_oauth($params) + public function __construct($params) { $this->CI =& get_instance(); $this->CI->load->helper('oauth'); diff --git a/libraries/Youtube.php b/libraries/Youtube.php index 5cefbd5..d7e9922 100644 --- a/libraries/Youtube.php +++ b/libraries/Youtube.php @@ -77,7 +77,7 @@ class Youtube * @param string $clientId The clientId issued by the YouTube dashboard * @param string $developerKey The developerKey issued by the YouTube dashboard */ - public function youtube($params) + public function __construct($params) { if(isset($params['apikey']))$this->_header['X-GData-Key'] = 'key='.$params['apikey']; $this->CI =& get_instance(); @@ -396,9 +396,9 @@ public function getUserFavorites($user = 'default', array $params = array()) return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}/favorites", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); } - public function getUserProfile($user = 'default') + public function getUserProfile($user = 'default', array $params = array()) { - return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}"); + return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}", array_merge(array('v'=>self::API_VERSION), $params)); } public function getUserActivity($user = 'default', array $params = array()) @@ -411,9 +411,9 @@ public function getUserActivity($user = 'default', array $params = array()) * * @return the youtube response xml. **/ - public function getInboxFeedForCurrentUser() + public function getInboxFeedForCurrentUser(array $params = array()) { - if($this->_access !== false)return $this->_response_request ("/{$this->_uris['INBOX_FEED_URI']}"); + if($this->_access !== false)return $this->_response_request ("/{$this->_uris['INBOX_FEED_URI']}", array_merge(array('v'=>self::API_VERSION), $params)); else return false; } diff --git a/spark.info b/spark.info index 4d00c59..7950023 100644 --- a/spark.info +++ b/spark.info @@ -1,4 +1,4 @@ name: youtube -version: 1.1.0 +version: 1.1.1 compatibility: 2.0.3 tags: ["youtube", "youtube api", "google oauth", "api"] From f6d796e6735453003c5ffb3e3132125096890577 Mon Sep 17 00:00:00 2001 From: w0rldart-laptop Date: Wed, 22 Aug 2012 17:18:55 +0200 Subject: [PATCH 3/8] most_viewed deprecated on july 23, 2012 for most_popular --- libraries/Youtube.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/Youtube.php b/libraries/Youtube.php index d7e9922..26213da 100644 --- a/libraries/Youtube.php +++ b/libraries/Youtube.php @@ -38,7 +38,7 @@ class Youtube private $_uris = array( 'STANDARD_TOP_RATED_URI' => 'feeds/api/standardfeeds/top_rated', - 'STANDARD_MOST_VIEWED_URI' => 'feeds/api/standardfeeds/most_viewed', + 'STANDARD_MOST_POPULAR_URI' => 'feeds/api/standardfeeds/most_popular', 'STANDARD_MOST_RECENT_URI' => 'feeds/api/standardfeeds/most_recent', 'STANDARD_RECENTLY_FEATURED_URI' => 'feeds/api/standardfeeds/recently_featured', 'STANDARD_WATCH_ON_MOBILE_URI' => 'feeds/api/standardfeeds/watch_on_mobile', @@ -317,9 +317,14 @@ public function getTopRatedVideoFeed(array $params = array()) return $this->_response_request("/{$this->_uris['STANDARD_TOP_RATED_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); } + public function getMostPopularVideoFeed(array $params = array()) + { + return $this->getMostViewedVideoFeed($params); + } + public function getMostViewedVideoFeed(array $params = array()) { - return $this->_response_request("/{$this->_uris['STANDARD_MOST_VIEWED_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); + return $this->_response_request("/{$this->_uris['STANDARD_MOST_POPULAR_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); } /** @@ -675,4 +680,4 @@ public function setVideoPositionInPlaylist($playlistEntryId, $playlistId, $posit } } // ./application/libraries -?> \ No newline at end of file +?> From 15d2c76d1d6cc57d6688b73ca7b8a4ea6e7ec5f3 Mon Sep 17 00:00:00 2001 From: w0rldart-laptop Date: Wed, 22 Aug 2012 17:37:24 +0200 Subject: [PATCH 4/8] most_viewed deprecated on july 23, 2012 for most_popular --- libraries/Youtube.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Youtube.php b/libraries/Youtube.php index 26213da..0b6ae5d 100644 --- a/libraries/Youtube.php +++ b/libraries/Youtube.php @@ -319,12 +319,12 @@ public function getTopRatedVideoFeed(array $params = array()) public function getMostPopularVideoFeed(array $params = array()) { - return $this->getMostViewedVideoFeed($params); + return $this->_response_request("/{$this->_uris['STANDARD_MOST_POPULAR_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); } public function getMostViewedVideoFeed(array $params = array()) { - return $this->_response_request("/{$this->_uris['STANDARD_MOST_POPULAR_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); + return $this->getMostPopularVideoFeed($params); } /** From 38ddb15e3ebb5b25db7d791f5efa208622933e4b Mon Sep 17 00:00:00 2001 From: w0rldart-laptop Date: Thu, 23 Aug 2012 10:31:37 +0200 Subject: [PATCH 5/8] Removed ?> at the end of Youtube.php file --- libraries/Youtube.php | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/Youtube.php b/libraries/Youtube.php index 0b6ae5d..a13d971 100644 --- a/libraries/Youtube.php +++ b/libraries/Youtube.php @@ -680,4 +680,3 @@ public function setVideoPositionInPlaylist($playlistEntryId, $playlistId, $posit } } // ./application/libraries -?> From e0e8bc74fcf3ce47b0f14ffc2eaa9de79f12b205 Mon Sep 17 00:00:00 2001 From: Jim Date: Mon, 25 Nov 2013 18:01:41 -0500 Subject: [PATCH 6/8] Fix for data request that always does a post _data_request was not respecting the method parameter when creating an HTTP header. --- libraries/Youtube.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Youtube.php b/libraries/Youtube.php index a13d971..4f74d5c 100644 --- a/libraries/Youtube.php +++ b/libraries/Youtube.php @@ -433,7 +433,7 @@ private function _data_request($uri, $metadata, $method = 'POST') { if($this->_access !== false) { - $header = "POST {$uri} HTTP/".self::HTTP_1.self::LINE_END; + $header = "{$method} {$uri} HTTP/".self::HTTP_1.self::LINE_END; $url = self::URI_BASE.substr($uri, 1); $encoding = "UTF-8"; $extra = "Content-Type: application/atom+xml; charset={$encoding}".self::LINE_END; From b66b7a032831c04a23bc36adb40cc01d83675d65 Mon Sep 17 00:00:00 2001 From: Jim Pannell Date: Thu, 28 Nov 2013 10:40:58 +0100 Subject: [PATCH 7/8] Added a new method called videoUpdate which enables you to change access control settings I'm specifically using this to make a video either listed ('list' = 'allowed') or unlisted ('list' = 'denied') in YouTube. Downside of this method is that we need to pass the media:group info through again in order for it not to be overwritten. Signed-off-by: Jim Pannell --- libraries/Youtube.php | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libraries/Youtube.php b/libraries/Youtube.php index 4f74d5c..642cda9 100644 --- a/libraries/Youtube.php +++ b/libraries/Youtube.php @@ -526,6 +526,38 @@ public function directUpload($path, $contenttype, $metadata, $filesize = false, return false; } + + /** + * Make a video either public or hidden + * Uses the yt:accessControl 'list' action with permission 'allowed' or 'denied' + * Need to include the media group info in order for data to not be overwritten/reset + * + * @param string $videoId The video you want to change. + * @param string $title The video's title. + * @param string $description The video's description. + * @param string $keywords The keywords you want to tag the video with + * @param string $category The category you want to put the video in + * @param string $permission Needs to be either 'allowed' or 'denied' + * @param string (optional) $user The user name whose account this video will go to. Defaults to the authenticated user. + * @param string (optional) $method Defaults to 'PUT'. + **/ + public function videoUpdate($videoId, $title, $description, $keywords, $category, $permission, $user = 'default', $method = 'PUT') + { + $uri = "/feeds/api/users/{$user}/uploads/{$videoId}"; + $xml = ''; + $xml .= ''; + $xml .= ''; + $xml .= ''.$title.''; + $xml .= ''.$description.''; + $xml .= ''.$category.''; + $xml .= ''.$keywords.''; + $xml .= ''; + $xml .= ''; + $xml .= ''; + return $this->_data_request($uri, $xml, $method); + } + + /** * Writes a file specified by path to the stream specified by the handle. * The file is written in chunks specified by the chunk size to decrease From 78d6e7fc256791a44f1cce3b2c6d63f64e92bd80 Mon Sep 17 00:00:00 2001 From: Jim Date: Fri, 10 Oct 2014 13:32:06 -0400 Subject: [PATCH 8/8] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 17b7b0f..77d094e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +NOTE: THIS LIBRARY IS DEPRECATED +================================ + +It is recommended that you use the official PHP API provided by YouTube at https://github.com/google/google-api-php-client + CodeIgniter Youtube API Library ===============================