├── 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 |
--------------------------------------------------------------------------------