├── spark.info ├── README.md ├── controllers └── example.php ├── helpers └── oauth_helper.php └── libraries ├── Google_oauth.php └── Youtube.php /spark.info: -------------------------------------------------------------------------------- 1 | name: youtube 2 | version: 1.1.1 3 | compatibility: 2.0.3 4 | tags: ["youtube", "youtube api", "google oauth", "api"] 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NOTE: THIS LIBRARY IS DEPRECATED 2 | ================================ 3 | 4 | It is recommended that you use the official PHP API provided by YouTube at https://github.com/google/google-api-php-client 5 | 6 | CodeIgniter Youtube API Library 7 | =============================== 8 | 9 | This library will let a user authenticate with youtube and perform actions such as uploading a video, commenting and rating videos, and getting video feeds. 10 | 11 | Some basic documentation can be found at http://code.google.com/apis/youtube/articles/codeigniter_library.html 12 | For the most up to date documentation checkout my blog at http://jimdoescode.blogspot.com 13 | 14 | Usage 15 | ------ 16 | Copy the files under your application directory. Then load the library like this: 17 | 18 | $params['apikey'] = 'YOUTUBE API KEY'; 19 | 20 | $this->load->library('youtube', $params); 21 | 22 | $this->youtube->getMostViewedVideoFeed(array('max-results'=>30)); 23 | 24 | License 25 | ------- 26 | This library is licensed under the MIT license. 27 | 28 | Sparks 29 | ------ 30 | You can also use this library with Sparks. Simply install using sparks then call. 31 | 32 | $this->load->spark('youtube/1.0.0'); 33 | 34 | Then load the library as specified in the usage. 35 | 36 | -------------------------------------------------------------------------------- /controllers/example.php: -------------------------------------------------------------------------------- 1 | load->library('session'); 9 | $this->load->helper('url'); 10 | } 11 | 12 | //CALL THIS METHOD FIRST BY GOING TO 13 | //www.your_url.com/index.php/request_youtube 14 | public function request_youtube() 15 | { 16 | $params['key'] = 'ENTER YOUR GOOGLE CONSUMER KEY'; 17 | $params['secret'] = 'ENTER YOUR GOOGLE CONSUMER SECRET'; 18 | $params['algorithm'] = 'HMAC-SHA1'; 19 | 20 | $this->load->library('google_oauth', $params); 21 | $data = $this->google_oauth->get_request_token(site_url('example/access_youtube')); 22 | $this->session->set_userdata('token_secret', $data['token_secret']); 23 | redirect($data['redirect']); 24 | } 25 | 26 | //This method will be redirected to automatically 27 | //once the user approves access of your application 28 | public function access_youtube() 29 | { 30 | $params['key'] = 'ENTER YOUR GOOGLE CONSUMER KEY'; 31 | $params['secret'] = 'ENTER YOUR GOOGLE CONSUMER SECRET'; 32 | $params['algorithm'] = 'HMAC-SHA1'; 33 | 34 | $this->load->library('google_oauth', $params); 35 | 36 | $oauth = $this->google_oauth->get_access_token(false, $this->session->userdata('token_secret')); 37 | 38 | $this->session->set_userdata('oauth_token', $oauth['oauth_token']); 39 | $this->session->set_userdata('oauth_token_secret', $oauth['oauth_token_secret']); 40 | } 41 | 42 | //This method can be called without having 43 | //done the oauth steps 44 | public function youtube_no_auth() 45 | { 46 | $params['apikey'] = 'ENTER YOUR GOOGLE YOUTUBE API KEY'; 47 | 48 | $this->load->library('youtube', $params); 49 | echo $this->youtube->getKeywordVideoFeed('pac man'); 50 | } 51 | 52 | //This method can be called after you executed 53 | //the oauth steps 54 | public function youtube_auth() 55 | { 56 | $params['apikey'] = 'ENTER YOUR GOOGLE YOUTUBE API KEY'; 57 | $params['oauth']['key'] = 'ENTER YOUR GOOGLE CONSUMER KEY'; 58 | $params['oauth']['secret'] = 'ENTER YOUR GOOGLE CONSUMER SECRET'; 59 | $params['oauth']['algorithm'] = 'HMAC-SHA1'; 60 | $params['oauth']['access_token'] = array('oauth_token'=>urlencode($this->session->userdata('oauth_token')), 61 | 'oauth_token_secret'=>urlencode($this->session->userdata('oauth_token_secret'))); 62 | 63 | $this->load->library('youtube', $params); 64 | echo $this->youtube->getUserUploads(); 65 | } 66 | 67 | public function direct_upload() 68 | { 69 | $videoPath = 'THE RELATIVE PATH ON YOUR SERVER TO THE VIDEO'; 70 | $videoType = 'THE CONTENT TYPE OF THE VIDEO'; //This is the mime type of the video ex: 'video/3gpp' 71 | 72 | $params['apikey'] = 'ENTER YOUR GOOGLE YOUTUBE API KEY'; 73 | $params['oauth']['key'] = 'ENTER YOUR GOOGLE CONSUMER KEY'; 74 | $params['oauth']['secret'] = 'ENTER YOUR GOOGLE CONSUMER SECRET'; 75 | $params['oauth']['algorithm'] = 'HMAC-SHA1'; 76 | $params['oauth']['access_token'] = array('oauth_token'=>urlencode($this->session->userdata('oauth_token')), 77 | 'oauth_token_secret'=>urlencode($this->session->userdata('oauth_token_secret'))); 78 | $this->load->library('youtube', $params); 79 | 80 | $metadata = 'Test Direct UploadTest Direct Uploading.Peopletest'; 81 | echo $this->youtube->directUpload($videoPath, $videoType, $metadata); 82 | } 83 | } 84 | 85 | /* End of file example.php */ 86 | /* Location: ./application/controllers/example.php */ -------------------------------------------------------------------------------- /helpers/oauth_helper.php: -------------------------------------------------------------------------------- 1 | $value) 55 | { 56 | //Don't include the token secret into the base string 57 | if(strtolower($key) != 'oauth_token_secret')$oauth .= "&{$key}={$value}"; 58 | } 59 | $data .= urlencode(substr($oauth, 1)); 60 | $secret .= '&'.$parameters['oauth_token_secret']; 61 | 62 | return base64_encode(hash_hmac('sha1', $data, $secret, true)); 63 | } 64 | 65 | /** 66 | * Signs an array of oauth parameters according to the 1.0 spec using 67 | * the rsa-sha1 hasing algorithm 68 | * 69 | * @param string $method either GET or POST 70 | * @param string $baseurl the baseurl we are authenticating againts 71 | * @param string $certfile the location of your private certificate file 72 | * @param array $parameters all parameters that need to be signed 73 | * @return string the signature 74 | */ 75 | function sign_rsa_sha1($method, $baseurl, $certfile, array $parameters) 76 | { 77 | $fp = fopen($certfile, "r"); 78 | $private = fread($fp, 8192); 79 | fclose($fp); 80 | 81 | $data = $method.'&'; 82 | $data .= urlencode($baseurl).'&'; 83 | $oauth = ''; 84 | ksort($parameters); 85 | 86 | foreach($parameters as $key => $value) 87 | $oauth .= "&{$key}={$value}"; 88 | $data .= urlencode(substr($oauth, 1)); 89 | 90 | $keyid = openssl_get_privatekey($private); 91 | openssl_sign($data, $signature, $keyid); 92 | openssl_free_key($keyid); 93 | 94 | return base64_encode($signature); 95 | } 96 | 97 | /** 98 | * Assembles the auth params array into a string that can 99 | * be put into an http header request. 100 | * 101 | * @param array $authparams the oauth parameters 102 | * @return string the header authorization portion with trailing \r\n 103 | */ 104 | function build_auth_string(array $authparams) 105 | { 106 | $header = "Authorization: OAuth "; 107 | $auth = ''; 108 | foreach($authparams AS $key=>$value) 109 | { 110 | //Don't include token secret 111 | if($key != 'oauth_token_secret')$auth .= ", {$key}=\"{$value}\""; 112 | } 113 | return $header.substr($auth, 2)."\r\n"; 114 | } 115 | 116 | /** 117 | * Assemble an associative array with oauth values 118 | * 119 | * @param string $baseurl the base url we are authenticating against. 120 | * @param string $key your consumer key 121 | * @param string $secret either your consumer secret key or the file location of your rsa private key. 122 | * @param array $extra additional oauth parameters that should be included (you must urlencode, if appropriate, before calling this function) 123 | * @param string $method either GET or POST 124 | * @param string $algo either HMAC-SHA1 or RSA-SHA1 (NOTE: this affects what you put in for the secret parameter) 125 | * @return array of all the oauth parameters 126 | */ 127 | function build_auth_array($baseurl, $key, $secret, $extra = array(), $method = 'GET', $algo = OAUTH_ALGORITHMS::RSA_SHA1) 128 | { 129 | $auth['oauth_consumer_key'] = $key; 130 | $auth['oauth_signature_method'] = $algo; 131 | $auth['oauth_timestamp'] = time(); 132 | $auth['oauth_nonce'] = md5(uniqid(rand(), true)); 133 | $auth['oauth_version'] = '1.0'; 134 | 135 | $auth = array_merge($auth, $extra); 136 | 137 | //We want to remove any query parameters from the base url 138 | $urlsegs = explode("?", $baseurl); 139 | $baseurl = $urlsegs[0]; 140 | 141 | //If there are any query parameters we need to make sure they 142 | //get signed with the rest of the auth data. 143 | $signing = $auth; 144 | if(count($urlsegs) > 1) 145 | { 146 | preg_match_all("/([\w\-]+)\=([\w\d\-\%\.\$\+\*]+)\&?/", $urlsegs[1], $matches); 147 | $signing = $signing + array_combine($matches[1], $matches[2]); 148 | } 149 | 150 | if(strtoupper($algo) == OAUTH_ALGORITHMS::HMAC_SHA1)$auth['oauth_signature'] = sign_hmac_sha1($method, $baseurl, $secret, $signing); 151 | else if(strtoupper($algo) == OAUTH_ALGORITHMS::RSA_SHA1)$auth['oauth_signature'] = sign_rsa_sha1 ($method, $baseurl, $secret, $signing); 152 | 153 | $auth['oauth_signature'] = urlencode($auth['oauth_signature']); 154 | return $auth; 155 | } 156 | 157 | /** 158 | * Creates the authorization portion of a header NOTE: This does not 159 | * create a complete http header. Also NOTE: the oauth_token parameter 160 | * should be passed in using the $extra array. 161 | * 162 | * @param string $baseurl the base url we are authenticating against. 163 | * @param string $key your consumer key 164 | * @param string $secret either your consumer secret key or the file location of your rsa private key. 165 | * @param array $extra additional oauth parameters that should be included (you must urlencode a parameter, if appropriate, before calling this function) 166 | * @param string $method either GET or POST 167 | * @param string $algo either HMAC-SHA1 or RSA-SHA1 (NOTE: this affects what you put in for the secret parameter) 168 | * @return string the header authorization portion with trailing \r\n 169 | */ 170 | function get_auth_header($baseurl, $key, $secret, $extra = array(), $method = 'GET', $algo = OAUTH_ALGORITHMS::RSA_SHA1) 171 | { 172 | $auth = build_auth_array($baseurl, $key, $secret, $extra, $method, $algo); 173 | return build_auth_string($auth); 174 | } 175 | 176 | /* ./application/helpers/oauth_helper.php */ 177 | ?> 178 | -------------------------------------------------------------------------------- /libraries/Google_oauth.php: -------------------------------------------------------------------------------- 1 | 'example.com', 'secret'=>'mysecret'); 57 | * Note that the secret should either be a hash string for 58 | * HMAC signatures or a file path string for RSA signatures. 59 | * 60 | * @param array $params 61 | */ 62 | public function __construct($params) 63 | { 64 | $this->CI =& get_instance(); 65 | $this->CI->load->helper('oauth'); 66 | //Set defaults for method and algorithm if they are not specified 67 | if(!array_key_exists('method', $params))$params['method'] = 'GET'; 68 | if(!array_key_exists('algorithm', $params))$params['algorithm'] = OAUTH_ALGORITHMS::RSA_SHA1; 69 | 70 | $this->_consumer = $params; 71 | } 72 | 73 | /** 74 | * This is called to begin the oauth token exchange. This should only 75 | * need to be called once for a user, provided they allow oauth access. 76 | * It will return a URL that your site should redirect to, allowing the 77 | * user to login and accept your application. 78 | * 79 | * @param string $callback the page on your site you wish to return to 80 | * after the user grants your application access. 81 | * @return mixed either the URL to redirect to, or if they specified HMAC 82 | * signing an array with the token_secret and the redirect url 83 | */ 84 | public function get_request_token($callback) 85 | { 86 | $baseurl = self::SCHEME.'://'.self::HOST.self::REQUEST_URI; 87 | 88 | //Generate an array with the initial oauth values we need 89 | $auth = build_auth_array($baseurl, $this->_consumer['key'], $this->_consumer['secret'], 90 | array('oauth_callback'=>urlencode($callback), 'scope'=>urlencode(self::SCOPE)), 91 | $this->_consumer['method'], $this->_consumer['algorithm']); 92 | //Create the "Authorization" portion of the header 93 | $str = ''; 94 | foreach($auth AS $key=>$value) 95 | if($key != 'scope')$str .= ",{$key}=\"{$value}\"";//Do not include scope in the Authorization string. 96 | $str = substr($str, 1); 97 | $str = 'Authorization: OAuth '.$str; 98 | //Send it 99 | $response = $this->_connect("{$baseurl}?scope={$auth['scope']}", $str); 100 | //We should get back a request token and secret which 101 | //we will add to the redirect url. 102 | parse_str($response, $resarray); 103 | //Return the full redirect url and let the user decide what to do from there. 104 | $redirect = self::SCHEME.'://'.self::HOST.self::AUTHORIZE_URI."?oauth_token={$resarray['oauth_token']}"; 105 | //If they are using HMAC then we need to return the token secret for them to store. 106 | if($this->_consumer['algorithm'] == OAUTH_ALGORITHMS::RSA_SHA1)return $redirect; 107 | else return array('token_secret'=>$resarray['oauth_token_secret'], 'redirect'=>$redirect); 108 | } 109 | 110 | /** 111 | * This is called to finish the oauth token exchange. This too should 112 | * only need to be called once for a user. The token returned should 113 | * be stored in your database for that particular user. 114 | * 115 | * @param string $token this is the oauth_token returned with your callback url 116 | * @param string $secret this is the token secret supplied from the request (Only required if using HMAC) 117 | * @param string $verifier this is the oauth_verifier returned with your callback url 118 | * @return array access token and token secret 119 | */ 120 | public function get_access_token($token = false, $secret = false, $verifier = false) 121 | { 122 | //If no request token was specified then attempt to get one from the url 123 | if($token === false && isset($_GET['oauth_token']))$token = $_GET['oauth_token']; 124 | if($verifier === false && isset($_GET['oauth_verifier']))$verifier = $_GET['oauth_verifier']; 125 | //If all else fails attempt to get it from the request uri. 126 | if($token === false && $verifier === false) 127 | { 128 | $uri = $_SERVER['REQUEST_URI']; 129 | $uriparts = explode('?', $uri); 130 | 131 | $authfields = array(); 132 | parse_str($uriparts[1], $authfields); 133 | $token = $authfields['oauth_token']; 134 | $verifier = $authfields['oauth_verifier']; 135 | } 136 | 137 | $tokenddata = array('oauth_token'=>urlencode($token), 'oauth_verifier'=>urlencode($verifier)); 138 | if($secret !== false)$tokenddata['oauth_token_secret'] = urlencode($secret); 139 | 140 | $baseurl = self::SCHEME.'://'.self::HOST.self::ACCESS_URI; 141 | //Include the token and verifier into the header request. 142 | $auth = get_auth_header($baseurl, $this->_consumer['key'], $this->_consumer['secret'], 143 | $tokenddata, $this->_consumer['method'], $this->_consumer['algorithm']); 144 | $response = $this->_connect($baseurl, $auth); 145 | //Parse the response into an array it should contain 146 | //both the access token and the secret key. (You only 147 | //need the secret key if you use HMAC-SHA1 signatures.) 148 | parse_str($response, $oauth); 149 | //Return the token and secret for storage 150 | return $oauth; 151 | } 152 | 153 | /** 154 | * Connects to the server and sends the request, 155 | * then returns the response from the server. 156 | * @param $url 157 | * @param $auth 158 | * @return 159 | */ 160 | private function _connect($url, $auth) 161 | { 162 | $ch = curl_init($url); 163 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ; 164 | curl_setopt($ch, CURLOPT_SSLVERSION,3); 165 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 166 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); 167 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 168 | curl_setopt($ch, CURLOPT_HTTPHEADER, explode("\r\n", $auth)); 169 | curl_setopt($ch, CURLINFO_HEADER_OUT, true); 170 | 171 | $response = curl_exec($ch); 172 | 173 | if(self::DEBUG) 174 | { 175 | error_log(print_r(curl_getinfo($ch), true)); 176 | error_log($response); 177 | } 178 | curl_close($ch); 179 | return $response; 180 | } 181 | } 182 | // ./system/application/libraries 183 | ?> 184 | -------------------------------------------------------------------------------- /libraries/Youtube.php: -------------------------------------------------------------------------------- 1 | 'feeds/api/standardfeeds/top_rated', 41 | 'STANDARD_MOST_POPULAR_URI' => 'feeds/api/standardfeeds/most_popular', 42 | 'STANDARD_MOST_RECENT_URI' => 'feeds/api/standardfeeds/most_recent', 43 | 'STANDARD_RECENTLY_FEATURED_URI' => 'feeds/api/standardfeeds/recently_featured', 44 | 'STANDARD_WATCH_ON_MOBILE_URI' => 'feeds/api/standardfeeds/watch_on_mobile', 45 | 'PLAYLIST_URI' => 'feeds/api/playlists', 46 | 'USER_URI' => 'feeds/api/users', 47 | 'INBOX_FEED_URI' => 'feeds/api/users/default/inbox', 48 | 'SUBSCRIPTION_URI' => 'feeds/api/users/default/subscriptions', 49 | 'FAVORITE_URI' => 'feeds/api/users/default/favorites', 50 | 'VIDEO_URI' => 'feeds/api/videos', 51 | 'USER_UPLOADS_REL' => 'schemas/2007#user.uploads', 52 | 'USER_PLAYLISTS_REL' => 'schemas/2007#user.playlists', 53 | 'USER_SUBSCRIPTIONS_REL' => 'schemas/2007#user.subscriptions', 54 | 'USER_CONTACTS_REL' => 'schemas/2007#user.contacts', 55 | 'USER_FAVORITES_REL' => 'schemas/2007#user.favorites', 56 | 'VIDEO_RESPONSES_REL' => 'schemas/2007#video.responses', 57 | 'VIDEO_RATINGS_REL' => 'schemas/2007#video.ratings', 58 | 'VIDEO_COMPLAINTS_REL' => 'schemas/2007#video.complaints', 59 | 'PLAYLIST_REL' => 'schemas/2007#playlist', 60 | 'IN_REPLY_TO_SCHEME' => 'schemas/2007#in-reply-to', 61 | 'UPLOAD_TOKEN_REQUEST' => 'action/GetUploadToken' 62 | ); 63 | 64 | private $_header = array( 65 | 'Host'=>self::HOST, 66 | 'Connection'=>'close', 67 | 'User-Agent'=>'CodeIgniter', 68 | 'Accept-encoding'=>'identity' 69 | ); 70 | 71 | private $_oauth = array(); 72 | private $_access = false; 73 | 74 | /** 75 | * Create YouTube object 76 | * 77 | * @param string $clientId The clientId issued by the YouTube dashboard 78 | * @param string $developerKey The developerKey issued by the YouTube dashboard 79 | */ 80 | public function __construct($params) 81 | { 82 | if(isset($params['apikey']))$this->_header['X-GData-Key'] = 'key='.$params['apikey']; 83 | $this->CI =& get_instance(); 84 | if(isset($params['oauth'])) 85 | { 86 | $this->_oauth['key'] = $params['oauth']['key']; 87 | $this->_oauth['secret'] = $params['oauth']['secret']; 88 | $this->_oauth['algorithm'] = $params['oauth']['algorithm']; 89 | $this->_access = $params['oauth']['access_token']; 90 | } 91 | } 92 | 93 | /** 94 | * Builds out an http header based on the specified parameters. 95 | * 96 | * @param $url string the url this header will go to. 97 | * @param $prepend any header data that needs to be added to the header before it is built. 98 | * @param $append any header data that needs to be added after the header is built. 99 | * @param $method the http method to be used 'POST', 'GET', 'PUT' etc. 100 | * return string the http header. 101 | **/ 102 | private function _build_header($url = false, $prepend = false, $append = false, $method = self::METHOD) 103 | { 104 | $str = $prepend === false ? '' : $prepend; 105 | foreach($this->_header AS $key=>$value) 106 | $str .= $key.": ".$value.self::LINE_END; 107 | if($this->_access !== false && $url !== false) 108 | { 109 | $this->CI->load->helper('oauth_helper'); 110 | $str .= get_auth_header($url, $this->_oauth['key'], $this->_oauth['secret'], $this->_access, $method, $this->_oauth['algorithm']); 111 | } 112 | $str .= $append === false ? '' : $append; 113 | 114 | return $str; 115 | } 116 | 117 | /** 118 | * Connects to the configured server and returns a handle for I/O 119 | **/ 120 | private function _connect($host = self::HOST, $port = self::PORT, $ssl = false) 121 | { 122 | $connect = $ssl === false ? 'tcp' : 'ssl'; 123 | $opts = array(self::SCHEME=>array('method'=>self::METHOD, 'header'=>$this->_build_header())); 124 | $context = stream_context_create($opts); 125 | $handle = stream_socket_client($connect.'://'.$host.':'.$port, $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context); 126 | 127 | return $handle; 128 | } 129 | 130 | /** 131 | * Checks that the response from the server after we make our request is good. 132 | * If it isn't then we log the response we got and return false. 133 | **/ 134 | private function _check_status($handle) 135 | { 136 | $gotStatus = false; 137 | $response = ''; 138 | $resparray = array(); 139 | while(($line = fgets($handle)) !== false && !$this->_timedout($handle)) 140 | { 141 | $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false); 142 | if($gotStatus) 143 | { 144 | $response .= $line; 145 | array_push($resparray, $line); 146 | if(rtrim($line) === '')break; 147 | } 148 | } 149 | 150 | $matches = explode(' ', $resparray[0]); 151 | $status = $gotStatus ? intval($matches[1]) : 0; 152 | if($status < 200 || $status > 299) 153 | { 154 | error_log('YouTube library received bad response: '.$response); 155 | if(!self::DEBUG)return false; 156 | else return $response; 157 | } 158 | return true; 159 | } 160 | 161 | private function _read($handle) 162 | { 163 | if($this->_check_status($handle) !== true)return false; 164 | $response = ''; 165 | //Get the chunk size 166 | $chunksize = rtrim(fgets($handle)); 167 | //Convert hex chunk size to int 168 | if(ctype_xdigit($chunksize))$chunksize = hexdec($chunksize); 169 | else //We aren't dealing with a chunksize so set the response. 170 | { 171 | $response = $chunksize; 172 | $chunksize = 0; 173 | } 174 | 175 | if(self::DEBUG)error_log("\nCHUNKSIZE: {$chunksize}"); 176 | 177 | while($chunksize > 0 && !$this->_timedout($handle)) 178 | { 179 | $line = fgets($handle, $chunksize); 180 | //If fgets stops on a newline before reaching 181 | //chunksize. Loop till we get to the chunksize. 182 | while(strlen($line) < $chunksize) 183 | $line .= fgets($handle); 184 | 185 | $response .= rtrim($line); 186 | if(self::DEBUG)error_log("\nCHUNK: {$line}"); 187 | 188 | $chunksize = rtrim(fgets($handle)); 189 | //If we have a valid number for chunksize and we 190 | //didn't get an error while reading the last line 191 | if(ctype_xdigit($chunksize) && $line !== false)$chunksize = hexdec($chunksize); 192 | else break; 193 | 194 | if(self::DEBUG)error_log("\nCHUNKSIZE: {$chunksize}"); 195 | } 196 | if(self::DEBUG)error_log("\nRESPONSE: {$response}"); 197 | return $response; 198 | } 199 | 200 | /** 201 | * Writes the specified request to the file handle. 202 | **/ 203 | private function _write($handle, $request) 204 | { 205 | if(self::DEBUG)error_log($request); 206 | fwrite($handle, $request); 207 | return $request; 208 | } 209 | 210 | /** 211 | * Checks that the specified file handle hasn't timed out. 212 | **/ 213 | private function _timedout($handle) 214 | { 215 | if($handle) 216 | { 217 | $info = stream_get_meta_data($handle); 218 | return $info['timed_out']; 219 | } 220 | return false; 221 | } 222 | 223 | /** 224 | * Executes a request that does not pass data, and returns the response. 225 | * 226 | * @param string $uri The URI that corresponds to the data we want. 227 | * @param array $params additional parameters to pass 228 | * @return the xml response from youtube. 229 | **/ 230 | private function _response_request($uri, array $params = array()) 231 | { 232 | if(!empty($params))$uri .= '?'.http_build_query($params); 233 | $request = self::METHOD." {$uri} HTTP/".self::HTTP_1.self::LINE_END; 234 | 235 | $url = self::URI_BASE.substr($uri, 1); 236 | 237 | $fullrequest = $this->_build_header($url, $request, self::LINE_END); 238 | 239 | if(self::DEBUG)error_log($fullrequest); 240 | 241 | $handle = $this->_connect(); 242 | $this->_write($handle, $fullrequest); 243 | $output = $this->_read($handle); 244 | 245 | fclose($handle); 246 | $handle = null; 247 | 248 | return $output; 249 | } 250 | 251 | /** 252 | * Retrieves a specific video entry. 253 | * 254 | * @param $videoId The ID of the video to retrieve. 255 | * @param $fullEntry (optional) Retrieve the full metadata for the entry. 256 | * Only possible if entry belongs to currently authenticated user. 257 | * @return the xml response from youtube 258 | */ 259 | public function getVideoEntry($videoId, $fullEntry = false, array $params = array()) 260 | { 261 | if($fullEntry)return $this->_response_request("/{$this->_uris['USER_URI']}/default/uploads/{$videoId}", $params); 262 | else return $this->_response_request("/{$this->_uris['VIDEO_URI']}/{$videoId}", $params); 263 | } 264 | 265 | /** 266 | * Retrieves a feed of videos related to the specified video ID. 267 | * 268 | * @param string $videoId The videoId of interest 269 | * @param array $params additional parameters to pass to youtube see: http://code.google.com/apis/youtube/2.0/reference.html#Query_parameter_definitions 270 | * @return the xml response from youtube. 271 | */ 272 | public function getRelatedVideoFeed($videoId, array $params = array()) 273 | { 274 | return $this->_response_request("/{$this->_uris['VIDEO_URI']}/{$videoId}/related", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 275 | } 276 | 277 | /** 278 | * Retrieves a feed of video responses related to the specified video ID. 279 | * 280 | * @param string $videoId The videoId of interest 281 | * @param array $params additional parameters to pass to youtube see: http://code.google.com/apis/youtube/2.0/reference.html#Query_parameter_definitions 282 | * @return the xml response from youtube. 283 | */ 284 | public function getVideoResponseFeed($videoId, array $params = array()) 285 | { 286 | return $this->_response_request("/{$this->_uris['VIDEO_URI']}/{$videoId}/responses", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 287 | } 288 | 289 | /** 290 | * Retrieves a feed of videos based on an array of keywords. 291 | * 292 | * @param string $keywords Words to search by. Use "" for exact search, - for not and | for or. 293 | * @param array $params additional parameters to pass to youtube see: http://code.google.com/apis/youtube/2.0/reference.html#Query_parameter_definitions 294 | * @return the xml response from youtube. 295 | */ 296 | public function getKeywordVideoFeed($keywords, array $params = array()) 297 | { 298 | //Only need to convert spaces the rest get converted later. 299 | $params['q'] = str_replace(' ', '+', $keywords); 300 | return $this->_response_request("/{$this->_uris['VIDEO_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 301 | } 302 | 303 | /** 304 | * Retrieves a feed of video comments related to the specified video ID. 305 | * 306 | * @param string $videoId The videoId of interest 307 | * @param array $params additional parameters to pass to youtube see: http://code.google.com/apis/youtube/2.0/reference.html#Query_parameter_definitions 308 | * @return the xml response from youtube. 309 | */ 310 | public function getVideoCommentFeed($videoId, array $params = array()) 311 | { 312 | return $this->_response_request("/{$this->_uris['VIDEO_URI']}/{$videoId}/comments", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 313 | } 314 | 315 | public function getTopRatedVideoFeed(array $params = array()) 316 | { 317 | return $this->_response_request("/{$this->_uris['STANDARD_TOP_RATED_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 318 | } 319 | 320 | public function getMostPopularVideoFeed(array $params = array()) 321 | { 322 | return $this->_response_request("/{$this->_uris['STANDARD_MOST_POPULAR_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 323 | } 324 | 325 | public function getMostViewedVideoFeed(array $params = array()) 326 | { 327 | return $this->getMostPopularVideoFeed($params); 328 | } 329 | 330 | /** 331 | * Retrieves a feed of the most recently uploaded videos. 332 | * 333 | * @param array $params additional parameters to pass to youtube see: http://code.google.com/apis/youtube/2.0/reference.html#Query_parameter_definitions 334 | * @return the xml response from youtube. 335 | */ 336 | public function getMostRecentVideoFeed(array $params = array()) 337 | { 338 | return $this->_response_request("/{$this->_uris['STANDARD_MOST_RECENT_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 339 | } 340 | 341 | public function getRecentlyFeaturedVideoFeed(array $params = array()) 342 | { 343 | return $this->_response_request("/{$this->_uris['STANDARD_RECENTLY_FEATURED_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 344 | } 345 | 346 | public function getWatchOnMobileVideoFeed(array $params = array()) 347 | { 348 | return $this->_response_request("/{$this->_uris['STANDARD_WATCH_ON_MOBILE_URI']}", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 349 | } 350 | 351 | /** 352 | * Retrieves a feed of playlist urls that the specified user manages. 353 | * 354 | * @param string $user the user whose playlists you wish to retrieve 355 | * @param array $params additional parameters to pass. 356 | * @return the xml response from youtube. 357 | */ 358 | public function getUserPlaylistFeed($user = 'default', array $params = array()) 359 | { 360 | return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}/playlists", array_merge(array('v'=>self::API_VERSION), $params)); 361 | } 362 | 363 | /** 364 | * Retrieves a feed of videos for the specified playlist. 365 | * 366 | * @param string $playlist the id of the playlist you wish to retrieve 367 | * @param array $params additional parameters to pass 368 | * @return the xml response from youtube. 369 | */ 370 | public function getPlaylistFeed($playlist, array $params = array()) 371 | { 372 | return $this->_response_request("/{$this->_uris['PLAYLIST_URI']}/{$playlist}", array_merge(array('v'=>self::API_VERSION), $params)); 373 | } 374 | 375 | public function getSubscriptionFeed($user = 'default', array $params = array()) 376 | { 377 | return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}/subscription", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 378 | } 379 | 380 | public function getContactFeed($user = 'default', array $params = array()) 381 | { 382 | return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}/contacts", array_merge(array('v'=>self::API_VERSION), $params)); 383 | } 384 | 385 | /** 386 | * Get all of the uploads the specified user has made to youtube. 387 | * If no user is specified then the currently authenticated user 388 | * is used. 389 | * 390 | * @param string $user the youtube user name of the user whose uploads you want. 391 | * @param array $params additional parameters to pass to youtube see: http://code.google.com/apis/youtube/2.0/reference.html#Query_parameter_definitions 392 | * @return the xml response from youtube. 393 | **/ 394 | public function getUserUploads($user = 'default', array $params = array()) 395 | { 396 | return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}/uploads", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 397 | } 398 | 399 | public function getUserFavorites($user = 'default', array $params = array()) 400 | { 401 | return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}/favorites", array_merge(array('start-index'=>1, 'max-results'=>10), $params)); 402 | } 403 | 404 | public function getUserProfile($user = 'default', array $params = array()) 405 | { 406 | return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}", array_merge(array('v'=>self::API_VERSION), $params)); 407 | } 408 | 409 | public function getUserActivity($user = 'default', array $params = array()) 410 | { 411 | return $this->_response_request("/{$this->_uris['USER_URI']}/{$user}/events", array_merge(array('v'=>self::API_VERSION), $params)); 412 | } 413 | 414 | /** 415 | * Get a feed of the currently authenticated users inbox. 416 | * 417 | * @return the youtube response xml. 418 | **/ 419 | public function getInboxFeedForCurrentUser(array $params = array()) 420 | { 421 | if($this->_access !== false)return $this->_response_request ("/{$this->_uris['INBOX_FEED_URI']}", array_merge(array('v'=>self::API_VERSION), $params)); 422 | else return false; 423 | } 424 | 425 | /** 426 | * Executes a request and passes metadata, then returns the response. 427 | * 428 | * @param $uri the URI for this request. 429 | * @param $metadata the data to send for this request (usually XML) 430 | * @return mixed false if not authroized otherwise the response is returned. 431 | **/ 432 | private function _data_request($uri, $metadata, $method = 'POST') 433 | { 434 | if($this->_access !== false) 435 | { 436 | $header = "{$method} {$uri} HTTP/".self::HTTP_1.self::LINE_END; 437 | $url = self::URI_BASE.substr($uri, 1); 438 | $encoding = "UTF-8"; 439 | $extra = "Content-Type: application/atom+xml; charset={$encoding}".self::LINE_END; 440 | $extra .= "GData-Version: 2.0".self::LINE_END; 441 | mb_internal_encoding($encoding); 442 | 443 | $extra .= "Content-Length: ".mb_strlen($metadata.self::LINE_END).self::LINE_END.self::LINE_END; 444 | 445 | $fullrequest = $this->_build_header($url, $header, $extra, $method); 446 | $fullrequest .= $metadata.self::LINE_END; 447 | 448 | $handle = $this->_connect(); 449 | $this->_write($handle, $fullrequest); 450 | $output = $this->_read($handle); 451 | 452 | fclose($handle); 453 | $handle = null; 454 | 455 | return $output; 456 | } 457 | return false; 458 | } 459 | 460 | /** 461 | * Directly uploads videos stored on your server to the youtube servers. 462 | * 463 | * @param string $path The path on your server to the video to upload. 464 | * @param string $contenttype The mime-type of the video to upload. 465 | * @param string $metadata XML information about the video to upload. 466 | * @param int (optional) $filesize the size of the video to upload in bytes. The library will calculate it if not set. 467 | * @param string (optional) $user the user name whose account this video will go to. Defaults to the authenticated user. 468 | **/ 469 | public function directUpload($path, $contenttype, $metadata, $filesize = false, $user = 'default') 470 | { 471 | if($this->_access !== false) 472 | { 473 | $uri = "/{$this->_uris['USER_URI']}/{$user}/uploads"; 474 | $header = "POST {$uri} HTTP/".self::HTTP_1.self::LINE_END; 475 | //We use a special host for direct uploads. 476 | $host = 'uploads.gdata.youtube.com'; 477 | $url = "http://{$host}{$uri}"; 478 | $extra = "GData-Version: 2.0".self::LINE_END; 479 | //Add the file name to the slug parameter. 480 | $extra .= "Slug: ".basename($path).self::LINE_END; 481 | //Create a random boundary string. 482 | $this->CI->load->helper('string'); 483 | $boundary = random_string(); 484 | $extra .= "Content-Type: multipart/related; boundary=\"{$boundary}\"".self::LINE_END; 485 | 486 | //Build out the data portion of the request 487 | $data = "--{$boundary}".self::LINE_END; 488 | $data .= "Content-Type: application/atom+xml; charset=UTF-8".self::LINE_END.self::LINE_END; 489 | $data .= $metadata.self::LINE_END; 490 | $data .= "--{$boundary}".self::LINE_END; 491 | $data .= "Content-Type: ".$contenttype.self::LINE_END; 492 | $data .= "Content-Transfer-Encoding: binary".self::LINE_END.self::LINE_END; 493 | 494 | $end = self::LINE_END."--{$boundary}--".self::LINE_END; 495 | 496 | //If file size is not set then calculate it 497 | //NOTE: This may cause memory problems for large videos 498 | if($filesize === false)$filesize = filesize($path); 499 | 500 | $length = strlen($data) + intval($filesize) + strlen($end); 501 | 502 | //Calculate the size of the data portion. 503 | $extra .= "Content-Length: {$length}".self::LINE_END.self::LINE_END; 504 | $this->_header['Host'] = $host;//Swap the default host 505 | $start = $this->_build_header($url, $header, $extra, 'POST'); 506 | $this->_header['Host'] = self::HOST;//Revert the default host. 507 | $start .= $data; 508 | 509 | $handle = null; 510 | //Connect to the special upload host 511 | $handle = $this->_connect($host); 512 | //Write the request header 513 | $this->_write($handle, $start); 514 | //Write the file data 515 | $this->_write_file($handle, $path); 516 | //Write the ending 517 | $this->_write($handle, $end); 518 | 519 | $output = $this->_read($handle); 520 | 521 | fclose($handle); 522 | $handle = null; 523 | 524 | return $output; 525 | } 526 | return false; 527 | } 528 | 529 | 530 | /** 531 | * Make a video either public or hidden 532 | * Uses the yt:accessControl 'list' action with permission 'allowed' or 'denied' 533 | * Need to include the media group info in order for data to not be overwritten/reset 534 | * 535 | * @param string $videoId The video you want to change. 536 | * @param string $title The video's title. 537 | * @param string $description The video's description. 538 | * @param string $keywords The keywords you want to tag the video with 539 | * @param string $category The category you want to put the video in 540 | * @param string $permission Needs to be either 'allowed' or 'denied' 541 | * @param string (optional) $user The user name whose account this video will go to. Defaults to the authenticated user. 542 | * @param string (optional) $method Defaults to 'PUT'. 543 | **/ 544 | public function videoUpdate($videoId, $title, $description, $keywords, $category, $permission, $user = 'default', $method = 'PUT') 545 | { 546 | $uri = "/feeds/api/users/{$user}/uploads/{$videoId}"; 547 | $xml = ''; 548 | $xml .= ''; 549 | $xml .= ''; 550 | $xml .= ''.$title.''; 551 | $xml .= ''.$description.''; 552 | $xml .= ''.$category.''; 553 | $xml .= ''.$keywords.''; 554 | $xml .= ''; 555 | $xml .= ''; 556 | $xml .= ''; 557 | return $this->_data_request($uri, $xml, $method); 558 | } 559 | 560 | 561 | /** 562 | * Writes a file specified by path to the stream specified by the handle. 563 | * The file is written in chunks specified by the chunk size to decrease 564 | * the potential memory footprint. 565 | * 566 | * @param stream $handle Handle to the stream to write to 567 | * @param string $path Path of the file to read from 568 | * @param int $chunksize Size of each chunk that is read from the file. 569 | */ 570 | private function _write_file($handle, $path, $chunksize = 8192) 571 | { 572 | $filehandle = fopen($path, 'r'); 573 | while(!feof($filehandle)) 574 | fwrite($handle, fread($filehandle, $chunksize)); 575 | 576 | fclose($filehandle); 577 | $filehandle = null; 578 | } 579 | 580 | 581 | /** 582 | * Makes a data request for a youtube upload token. 583 | * You must provide details for the video prior to 584 | * the request. These are specified in xml and are 585 | * passed as the metadata field. 586 | * 587 | * @param string $metadata XML information about the video about to be uploaded. 588 | * @return mixed false if not authorized otherwise the response is returned. 589 | **/ 590 | public function getFormUploadToken($metadata) 591 | { 592 | return $this->_data_request("/{$this->_uris['UPLOAD_TOKEN_REQUEST']}", $metadata); 593 | } 594 | 595 | /** 596 | * Add a comment to a video or a reply to another comment. 597 | * To reply to a comment you must specify the commentId 598 | * otherwise it is just a regular comment. 599 | * 600 | * @param string $videoId the video the comment goes with. 601 | * @param string $comment the comment 602 | * @param string (optional) $commentId the id of the comment to reply to. 603 | * @return mixed false if not authenticated otherwise the http response is returned. 604 | **/ 605 | public function addComment($videoId, $comment, $commentId = false) 606 | { 607 | 608 | $uri = "/{$this->_uris['VIDEO_URI']}/{$videoId}/comments"; 609 | $url = self::URI_BASE.substr($uri, 1); 610 | 611 | $xml = ""; 612 | if($commentId !== false)$xml .= ""; 613 | $xml .= "{$comment}"; 614 | 615 | return $this->_data_request($uri, $xml); 616 | } 617 | 618 | /** 619 | * Add a video response to another video. 620 | * 621 | * @param string $videoId the youtube id of the video the response is to. 622 | * @param string $responseId the youtube id of the video response. 623 | * @return mixed false if not authenticated otherwise the http response is returned. 624 | **/ 625 | public function addVideoResponse($videoId, $responseId) 626 | { 627 | $uri = "/{$this->_uris['VIDEO_URI']}/{$videoId}/responses"; 628 | $xml = "{$responseId}"; 629 | 630 | return $this->_data_request($uri, $xml); 631 | } 632 | 633 | /** 634 | * Adds a numeric rating between 1 and 5 to the specified video 635 | * 636 | * @param string $videoId the youtube video id. 637 | * @param int $rating the numeric rating between 1 and 5. 638 | * @return mixed false if not authenticated or rating is invalid otherwise the http response is sent. 639 | **/ 640 | public function addNumericRating($videoId, $rating) 641 | { 642 | if(is_numeric($rating) && $rating > 0 && $rating < 6) 643 | { 644 | $xml = ""; 645 | return $this->_data_request("/{$this->_uris['VIDEO_URI']}/{$videoId}/ratings", $xml); 646 | } 647 | return false; 648 | } 649 | 650 | /** 651 | * Adds a like or dislike rating to the specified video. 652 | * 653 | * @param string $videoId the youtube video id. 654 | * @param bool $like boolean where true = like and false = dislike. 655 | * @return mixed false if not authenticated otherwise the http response is sent. 656 | **/ 657 | public function addLikeDislike($videoId, $like) 658 | { 659 | $xml = ""; 660 | return $this->_data_request("/{$this->_uris['VIDEO_URI']}/{$videoId}/ratings", $xml); 661 | } 662 | 663 | /** 664 | * Subscribes the currently authenticated user to the specified user. 665 | * 666 | * @param string $userId the user you want to subscribe to. 667 | * @return mixed false if not authenticated otherwise the http response is sent. 668 | */ 669 | public function addSubscription($userId) 670 | { 671 | $xml = "{$userId}"; 672 | return $this->_data_request("/{$this->_uris['SUBSCRIPTION_URI']}", $xml); 673 | } 674 | 675 | /** 676 | * Adds specified video as a favorite video. 677 | * 678 | * @param string $videoId the youtube video you want to add to favorites. 679 | * @return mixed false if not authenticated otherwise the http response is sent. 680 | */ 681 | public function addFavorite($videoId) 682 | { 683 | $xml = "{$videoId}"; 684 | return $this->_data_request("/{$this->_uris['FAVORITE_URI']}", $xml); 685 | } 686 | 687 | /** 688 | * Adds specified video to the specified playlist 689 | * 690 | * @param string $videoId the youtube video you want to add to the playlist. 691 | * @param string $playlistId the youtube playlist you want to add the video to. 692 | * @return mixed false if not authenticated otherwise the http response is sent. 693 | */ 694 | public function addVideoToPlaylist($videoId, $playlistId) 695 | { 696 | $xml = "{$videoId}"; 697 | return $this->_data_request("/{$this->_uris['PLAYLIST_URI']}/{$playlistId}", $xml); 698 | } 699 | 700 | /** 701 | * Sets the position of the specified video entry in the specified playlist 702 | * 703 | * @param string $playlistEntryId the youtube video entry you want to change the position. 704 | * @param string $playlistId the youtube playlist you want to change the position. 705 | * @param integer $position the position of the video in the playlist. 706 | * @return mixed false if not authenticated otherwise the http response is sent. 707 | */ 708 | public function setVideoPositionInPlaylist($playlistEntryId, $playlistId, $position) 709 | { 710 | $xml = "{$position}"; 711 | return $this->_data_request("/{$this->_uris['PLAYLIST_URI']}/{$playlistId}/{$playlistEntryId}", $xml, 'PUT'); 712 | } 713 | } 714 | // ./application/libraries 715 | --------------------------------------------------------------------------------