summaryrefslogtreecommitdiff
path: root/lib/php-youtube-api/src/Youtube.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/php-youtube-api/src/Youtube.php')
-rw-r--r--lib/php-youtube-api/src/Youtube.php678
1 files changed, 678 insertions, 0 deletions
diff --git a/lib/php-youtube-api/src/Youtube.php b/lib/php-youtube-api/src/Youtube.php
new file mode 100644
index 0000000..2ad7500
--- /dev/null
+++ b/lib/php-youtube-api/src/Youtube.php
@@ -0,0 +1,678 @@
+<?php
+
+namespace Madcoda\Youtube;
+
+use Madcoda\Youtube\Constants;
+
+/**
+ * Youtube Data API (mainly apis for retrieving data)
+ * @version 0.1
+ */
+class Youtube
+{
+
+ /*
+ * some constants for convenience
+ */
+
+ //order in search api
+ const ORDER_DATE = Constants::ORDER_DATE;
+ const ORDER_RATING = Constants::ORDER_RATING;
+ const ORDER_RELEVANCE = Constants::ORDER_RELEVANCE;
+ const ORDER_TITLE = Constants::ORDER_TITLE;
+ const ORDER_VIDEOCOUNT = Constants::ORDER_VIDEOCOUNT;
+ const ORDER_VIEWCOUNT = Constants::ORDER_VIEWCOUNT;
+
+ //eventType
+ const EVENT_TYPE_LIVE = Constants::EVENT_TYPE_LIVE;
+ const EVENT_TYPE_COMPLETED = Constants::EVENT_TYPE_COMPLETED;
+ const EVENT_TYPE_UPCOMING = Constants::EVENT_TYPE_UPCOMING;
+
+ //type in search api
+ const SEARCH_TYPE_CHANNEL = Constants::SEARCH_TYPE_CHANNEL;
+ const SEARCH_TYPE_PLAYLIST = Constants::SEARCH_TYPE_PLAYLIST;
+ const SEARCH_TYPE_VIDEO = Constants::SEARCH_TYPE_VIDEO;
+
+
+ /**
+ * The API Key
+ * @var string
+ */
+ protected $youtube_key;
+
+
+ /**
+ * @var string
+ */
+ protected $referer;
+
+ /**
+ * @var string
+ */
+ protected $sslPath = null;
+
+
+ /**
+ * @var array
+ */
+ public $APIs = array(
+ 'videos.list' => 'https://www.googleapis.com/youtube/v3/videos',
+ 'search.list' => 'https://www.googleapis.com/youtube/v3/search',
+ 'channels.list' => 'https://www.googleapis.com/youtube/v3/channels',
+ 'playlists.list' => 'https://www.googleapis.com/youtube/v3/playlists',
+ 'playlistItems.list' => 'https://www.googleapis.com/youtube/v3/playlistItems',
+ 'activities' => 'https://www.googleapis.com/youtube/v3/activities',
+ );
+
+
+ /**
+ * @var array
+ */
+ public $page_info = array();
+
+
+ /**
+ * Constructor
+ * $youtube = new Youtube(array('key' => 'KEY HERE'))
+ *
+ * @param array $params
+ * @throws \Exception
+ */
+ public function __construct($params = array(), $sslPath = null)
+ {
+ if (!is_array($params)) {
+ throw new \InvalidArgumentException('The configuration options must be an array.');
+ }
+
+ if (!array_key_exists('key', $params) || empty($params['key'])) {
+ throw new \InvalidArgumentException('Google API key is required, please visit http://code.google.com/apis/console');
+ }
+ $this->setApiKey($params['key']);
+
+ if (array_key_exists('referer', $params)) {
+ $this->setReferer($params['referer']);
+ }
+
+ if (array_key_exists('apis', $params)) {
+ $this->setAPIs($params['apis']);
+ }
+
+ if ($sslPath !== null) {
+ $this->sslPath = $sslPath;
+ }
+ }
+
+
+ /**
+ * Update the API key, useful if you want to switch
+ * multiple keys to avoid quota problem
+ * @param $apiKey
+ */
+ public function setApiKey($apiKey)
+ {
+ $this->youtube_key = $apiKey;
+ }
+
+ /**
+ * Override the API urls, so you can set them from a config
+ * @param array $APIs
+ */
+ public function setAPIs(array $APIs)
+ {
+ $this->APIs = $APIs;
+ }
+
+
+ public function setReferer($referer)
+ {
+ $this->referer = $referer;
+ }
+
+ /**
+ * @param $vId
+ * @return \StdClass
+ * @throws \Exception
+ */
+ public function getVideoInfo($vId)
+ {
+ $API_URL = $this->getApi('videos.list');
+ $params = array(
+ 'id' => $vId,
+ 'part' => 'id, snippet, contentDetails, player, statistics, status'
+ );
+
+ $apiData = $this->api_get($API_URL, $params);
+ return $this->decodeSingle($apiData);
+ }
+
+
+ /**
+ * @param $vIds
+ * @return \StdClass
+ * @throws \Exception
+ */
+ public function getVideosInfo($vIds)
+ {
+ $ids = is_array($vIds) ? implode(',', $vIds) : $vIds;
+ $API_URL = $this->getApi('videos.list');
+ $params = array(
+ 'id' => $ids,
+ 'part' => 'id, snippet, contentDetails, player, statistics, status'
+ );
+
+ $apiData = $this->api_get($API_URL, $params);
+ return $this->decodeList($apiData);
+ }
+
+
+ /**
+ * Simple search interface, this search all stuffs
+ * and order by relevance
+ *
+ * @param $q
+ * @param int $maxResults
+ * @return array
+ */
+ public function search($q, $maxResults = 10)
+ {
+ $params = array(
+ 'q' => $q,
+ 'part' => 'id, snippet',
+ 'maxResults' => $maxResults
+ );
+ return $this->searchAdvanced($params);
+ }
+
+
+ /**
+ * Search only videos
+ *
+ * @param string $q Query
+ * @param integer $maxResults number of results to return
+ * @param string $order Order by
+ * @return \StdClass API results
+ */
+ public function searchVideos($q, $maxResults = 10, $order = null)
+ {
+ $params = array(
+ 'q' => $q,
+ 'type' => 'video',
+ 'part' => 'id, snippet',
+ 'maxResults' => $maxResults
+ );
+ if (!empty($order)) {
+ $params['order'] = $order;
+ }
+
+ return $this->searchAdvanced($params);
+ }
+
+
+ /**
+ * Search only videos in the channel
+ *
+ * @param string $q
+ * @param string $channelId
+ * @param integer $maxResults
+ * @param string $order
+ * @return object
+ */
+ public function searchChannelVideos($q, $channelId, $maxResults = 10, $order = null)
+ {
+ $params = array(
+ 'q' => $q,
+ 'type' => 'video',
+ 'channelId' => $channelId,
+ 'part' => 'id, snippet',
+ 'maxResults' => $maxResults
+ );
+ if (!empty($order)) {
+ $params['order'] = $order;
+ }
+
+ return $this->searchAdvanced($params);
+ }
+
+
+ public function searchChannelLiveStream($q, $channelId, $maxResults = 10, $order = null)
+ {
+ $params = array(
+ 'q' => $q,
+ 'type' => 'video',
+ 'eventType' => 'live',
+ 'channelId' => $channelId,
+ 'part' => 'id, snippet',
+ 'maxResults' => $maxResults
+ );
+
+ if (!empty($order)) {
+ $params['order'] = $order;
+ }
+
+ return $this->searchAdvanced($params);
+ }
+
+
+ /**
+ * Generic Search interface, use any parameters specified in
+ * the API reference
+ *
+ * @param $params
+ * @param $pageInfo
+ * @return array
+ * @throws \Exception
+ */
+ public function searchAdvanced($params, $pageInfo = false)
+ {
+ $API_URL = $this->getApi('search.list');
+
+ if (empty($params) || !isset($params['q'])) {
+ throw new \InvalidArgumentException('at least the Search query must be supplied');
+ }
+
+ $apiData = $this->api_get($API_URL, $params);
+ if ($pageInfo) {
+ return array(
+ 'results' => $this->decodeList($apiData),
+ 'info' => $this->page_info
+ );
+ } else {
+ return $this->decodeList($apiData);
+ }
+ }
+
+
+ /**
+ * Generic Search Paginator, use any parameters specified in
+ * the API reference and pass through nextPageToken as $token if set.
+ *
+ * @param $params
+ * @param $token
+ * @return array
+ */
+ public function paginateResults($params, $token = null)
+ {
+ if (!is_null($token)) {
+ $params['pageToken'] = $token;
+ }
+ return $this->searchAdvanced($params, true);
+ }
+
+
+ /**
+ * @param $username
+ * @return \StdClass
+ * @throws \Exception
+ */
+ public function getChannelByName($username, $optionalParams = false)
+ {
+ $API_URL = $this->getApi('channels.list');
+ $params = array(
+ 'forUsername' => $username,
+ 'part' => 'id,snippet,contentDetails,statistics'
+ );
+ if ($optionalParams) {
+ $params = array_merge($params, $optionalParams);
+ }
+ $apiData = $this->api_get($API_URL, $params);
+ return $this->decodeSingle($apiData);
+ }
+
+
+ /**
+ * @param $id
+ * @return \StdClass
+ * @throws \Exception
+ */
+ public function getChannelById($id, $optionalParams = false)
+ {
+ $API_URL = $this->getApi('channels.list');
+ $params = array(
+ 'id' => $id,
+ 'part' => 'id,snippet,contentDetails,statistics'
+ );
+ if ($optionalParams) {
+ $params = array_merge($params, $optionalParams);
+ }
+ $apiData = $this->api_get($API_URL, $params);
+ return $this->decodeSingle($apiData);
+ }
+
+ /**
+ * @param array $ids
+ * @return \StdClass
+ * @throws \Exception
+ */
+ public function getChannelsById($ids = array(), $optionalParams = false)
+ {
+ $API_URL = $this->getApi('channels.list');
+ $params = array(
+ 'id' => implode(',', $ids),
+ 'part' => 'id,snippet,contentDetails,statistics'
+ );
+ if($optionalParams){
+ $params = array_merge($params, $optionalParams);
+ }
+ $apiData = $this->api_get($API_URL, $params);
+ return $this->decodeList($apiData);
+ }
+
+ /**
+ * @param $channelId
+ * @param array $optionalParams
+ * @return array
+ * @throws \Exception
+ */
+ public function getPlaylistsByChannelId($channelId, $optionalParams = array())
+ {
+ $API_URL = $this->getApi('playlists.list');
+ $params = array(
+ 'channelId' => $channelId,
+ 'part' => 'id, snippet, status'
+ );
+ if ($optionalParams) {
+ $params = array_merge($params, $optionalParams);
+ }
+ $apiData = $this->api_get($API_URL, $params);
+ return $this->decodeList($apiData);
+ }
+
+
+ /**
+ * @param $id
+ * @return \StdClass
+ * @throws \Exception
+ */
+ public function getPlaylistById($id)
+ {
+ $API_URL = $this->getApi('playlists.list');
+ $params = array(
+ 'id' => $id,
+ 'part' => 'id, snippet, status'
+ );
+ $apiData = $this->api_get($API_URL, $params);
+ return $this->decodeSingle($apiData);
+ }
+
+
+ /**
+ * @param $playlistId
+ * @return array
+ * @throws \Exception
+ */
+ public function getPlaylistItemsByPlaylistId($playlistId, $maxResults = 50)
+ {
+ $params = array(
+ 'playlistId' => $playlistId,
+ 'part' => 'id, snippet, contentDetails, status',
+ 'maxResults' => $maxResults
+ );
+ return $this->getPlaylistItemsByPlaylistIdAdvanced($params);
+ }
+
+
+ /**
+ * @param $params
+ * @param bool|false $pageInfo
+ * @return array
+ * @throws \Exception
+ */
+ public function getPlaylistItemsByPlaylistIdAdvanced($params, $pageInfo = false)
+ {
+ $API_URL = $this->getApi('playlistItems.list');
+
+ if (empty($params) || !isset($params['playlistId'])) {
+ throw new \InvalidArgumentException('at least the playlist id must be supplied');
+ }
+
+ $apiData = $this->api_get($API_URL, $params);
+ if ($pageInfo) {
+ return array(
+ 'results' => $this->decodeList($apiData),
+ 'info' => $this->page_info
+ );
+ } else {
+ return $this->decodeList($apiData);
+ }
+ }
+
+
+ /**
+ * @param $channelId
+ * @return array
+ * @throws \Exception
+ */
+ public function getActivitiesByChannelId($channelId, $optionalParams = false)
+ {
+ if (empty($channelId)) {
+ throw new \InvalidArgumentException('ChannelId must be supplied');
+ }
+ $API_URL = $this->getApi('activities');
+ $params = array(
+ 'channelId' => $channelId,
+ 'part' => 'id, snippet, contentDetails'
+ );
+ if ($optionalParams) {
+ $params = array_merge($params, $optionalParams);
+ }
+ $apiData = $this->api_get($API_URL, $params);
+ return $this->decodeList($apiData);
+ }
+
+
+ /**
+ * Parse a youtube URL to get the youtube Vid.
+ * Support both full URL (www.youtube.com) and short URL (youtu.be)
+ *
+ * @param string $youtube_url
+ * @throws \Exception
+ * @return string Video Id
+ */
+ public static function parseVIdFromURL($youtube_url)
+ {
+ $videoId = null;
+ if (strpos($youtube_url, 'youtube.com')) {
+ if (strpos($youtube_url, 'embed')) {
+ $path = static::_parse_url_path($youtube_url);
+ $videoId = substr($path, 7);
+ }
+ if ($params = static::_parse_url_query($youtube_url)) {
+ $videoId = isset($params['v']) ? $params['v'] : null;
+ }
+ } elseif (strpos($youtube_url, 'youtu.be')) {
+ $path = static::_parse_url_path($youtube_url);
+ $videoId = substr($path, 1);
+ }
+
+ if (empty($videoId)) {
+ throw new \Exception('The supplied URL does not look like a Youtube URL');
+ }
+
+ return $videoId;
+ }
+
+
+ /**
+ * Get the channel object by supplying the URL of the channel page
+ *
+ * @param string $youtube_url
+ * @throws \Exception
+ * @return object Channel object
+ */
+ public function getChannelFromURL($youtube_url)
+ {
+ if (strpos($youtube_url, 'youtube.com') === false) {
+ throw new \Exception('The supplied URL does not look like a Youtube URL');
+ }
+
+ $path = static::_parse_url_path($youtube_url);
+ if (strpos($path, '/channel') === 0) {
+ $segments = explode('/', $path);
+ $channelId = $segments[count($segments) - 1];
+ $channel = $this->getChannelById($channelId);
+ } elseif (strpos($path, '/user') === 0) {
+ $segments = explode('/', $path);
+ $username = $segments[count($segments) - 1];
+ $channel = $this->getChannelByName($username);
+ } else {
+ throw new \Exception('The supplied URL does not look like a Youtube Channel URL');
+ }
+
+ return $channel;
+ }
+
+
+ /*
+ * Internally used Methods, set visibility to public to enable more flexibility
+ */
+
+ /**
+ * @param $name
+ * @return mixed
+ */
+ public function getApi($name)
+ {
+ return $this->APIs[$name];
+ }
+
+
+ /**
+ * Decode the response from youtube, extract the single resource object.
+ * (Don't use this to decode the response containing list of objects)
+ *
+ * @param string $apiData the api response from youtube
+ * @throws \Exception
+ * @return \StdClass an Youtube resource object
+ */
+ public function decodeSingle(&$apiData)
+ {
+ $resObj = json_decode($apiData);
+ if (isset($resObj->error)) {
+ $msg = "Error " . $resObj->error->code . " " . $resObj->error->message;
+ if (isset($resObj->error->errors[0])) {
+ $msg .= " : " . $resObj->error->errors[0]->reason;
+ }
+ throw new \Exception($msg, $resObj->error->code);
+ } else {
+ if(!property_exists($resObj, 'items')){
+ return false;
+ }
+ $itemsArray = $resObj->items;
+ if (!is_array($itemsArray) || count($itemsArray) == 0) {
+ return false;
+ } else {
+ return $itemsArray[0];
+ }
+ }
+ }
+
+
+ /**
+ * Decode the response from youtube, extract the list of resource objects
+ *
+ * @param string $apiData response string from youtube
+ * @throws \Exception
+ * @return array Array of StdClass objects
+ */
+ public function decodeList(&$apiData)
+ {
+ $resObj = json_decode($apiData);
+ if (isset($resObj->error)) {
+ $msg = "Error " . $resObj->error->code . " " . $resObj->error->message;
+ if (isset($resObj->error->errors[0])) {
+ $msg .= " : " . $resObj->error->errors[0]->reason;
+ }
+ throw new \Exception($msg, $resObj->error->code);
+ } else {
+ $this->page_info = array(
+ 'resultsPerPage' => $resObj->pageInfo->resultsPerPage,
+ 'totalResults' => isset($resObj->pageInfo->totalResults) ? $resObj->pageInfo->totalResults : null,
+ 'kind' => $resObj->kind,
+ 'etag' => $resObj->etag,
+ 'prevPageToken' => null,
+ 'nextPageToken' => null
+ );
+ if (isset($resObj->prevPageToken)) {
+ $this->page_info['prevPageToken'] = $resObj->prevPageToken;
+ }
+ if (isset($resObj->nextPageToken)) {
+ $this->page_info['nextPageToken'] = $resObj->nextPageToken;
+ }
+
+ $itemsArray = $resObj->items;
+ if (!is_array($itemsArray) || count($itemsArray) == 0) {
+ return false;
+ } else {
+ return $itemsArray;
+ }
+ }
+ }
+
+
+ /**
+ * Using CURL to issue a GET request
+ *
+ * @param $url
+ * @param $params
+ * @return mixed
+ * @throws \Exception
+ */
+ public function api_get($url, $params)
+ {
+ //set the youtube key
+ $params['key'] = $this->youtube_key;
+
+ //boilerplates for CURL
+ $tuCurl = curl_init();
+ if ($this->sslPath !== null) {
+ curl_setopt($tuCurl, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($tuCurl, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($tuCurl, CURLOPT_CAINFO, __DIR__ . '/cert/cacert.pem');
+ curl_setopt($tuCurl, CURLOPT_CAPATH, __DIR__ . '/cert/cacert.pem');
+ }
+ curl_setopt($tuCurl, CURLOPT_URL, $url . (strpos($url, '?') === false ? '?' : '') . http_build_query($params));
+ if ($this->referer !== null) {
+ curl_setopt($tuCurl, CURLOPT_REFERER, $this->referer);
+ }
+ curl_setopt($tuCurl, CURLOPT_RETURNTRANSFER, 1);
+ $tuData = curl_exec($tuCurl);
+ if (curl_errno($tuCurl)) {
+ throw new \Exception('Curl Error : ' . curl_error($tuCurl), curl_errno($tuCurl));
+ }
+ return $tuData;
+ }
+
+
+ /**
+ * Parse the input url string and return just the path part
+ *
+ * @param string $url the URL
+ * @return string the path string
+ */
+ public static function _parse_url_path($url)
+ {
+ return parse_url($url, PHP_URL_PATH);
+ }
+
+
+ /**
+ * Parse the input url string and return an array of query params
+ *
+ * @param string $url the URL
+ * @return array array of query params
+ */
+ public static function _parse_url_query($url)
+ {
+ $queryString = parse_url($url, PHP_URL_QUERY);
+
+ $params = array();
+
+ parse_str($queryString, $params);
+
+ if (count($params) === 0) {
+ return $params;
+ }
+
+ return array_filter($params);
+ }
+}