|
1 | 1 | <?php |
2 | 2 |
|
3 | 3 | /** |
4 | | - * This sample retrieves reports created by a specific job by: |
| 4 | + * This sample supports the following use cases: |
5 | 5 | * |
6 | | - * 1. Listing the jobs using the "jobs.list" method. |
7 | | - * 2. Retrieving reports using the "reports.list" method. |
8 | | - * |
9 | | - * @author Ibrahim Ulukaya |
| 6 | + * 1. Retrieve reporting jobs by content owner: |
| 7 | + * Ex: php retrieve_reports.php --contentOwner=="CONTENT_OWNER_ID" |
| 8 | + * Ex: php retrieve_reports.php --contentOwner=="CONTENT_OWNER_ID" --includeSystemManaged==True |
| 9 | + * 2. Retrieving list of downloadable reports for a particular job: |
| 10 | + * Ex: php retrieve_reports.php --contentOwner=="CONTENT_OWNER_ID" --jobId="JOB_ID" |
| 11 | + * 3. Download a report: |
| 12 | + * Ex: php retrieve_reports.php --contentOwner=="CONTENT_OWNER_ID" --downloadUrl="DOWNLOAD_URL" --outputFile="report.txt" |
10 | 13 | */ |
11 | 14 |
|
12 | 15 | /** |
|
18 | 21 | * $ composer require google/apiclient:~2.0 |
19 | 22 | */ |
20 | 23 | if (!file_exists(__DIR__ . '/vendor/autoload.php')) { |
21 | | - throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"'); |
| 24 | + throw new \Exception('please run "composer require google/apiclient:~2.2.0" in "' . __DIR__ .'"'); |
22 | 25 | } |
23 | 26 |
|
24 | 27 | require_once __DIR__ . '/vendor/autoload.php'; |
25 | 28 | session_start(); |
26 | 29 |
|
27 | 30 |
|
| 31 | +define('CREDENTIALS_PATH', '~/.credentials/youtube-php.json'); |
| 32 | + |
| 33 | +$longOptions = array( |
| 34 | + 'contentOwner::', |
| 35 | + 'downloadUrl::', |
| 36 | + 'includeSystemManaged::', |
| 37 | + 'jobId::', |
| 38 | + 'outputFile::', |
| 39 | +); |
| 40 | + |
| 41 | +$options = getopt('', $longOptions); |
| 42 | + |
| 43 | +$CONTENT_OWNER_ID = ($options['contentOwner'] ? $options['contentOwner'] : ''); |
| 44 | +$DOWNLOAD_URL = (array_key_exists('downloadUrl', $options) ? |
| 45 | + $options['downloadUrl'] : ''); |
| 46 | +$INCLUDE_SYSTEM_MANAGED = (array_key_exists('includeSystemManaged', $options) ? |
| 47 | + $options['includeSystemManaged'] : ''); |
| 48 | +$JOB_ID = (array_key_exists('jobId', $options) ? $options['jobId'] : ''); |
| 49 | +$OUTPUT_FILE = (array_key_exists('outputFile', $options) ? |
| 50 | + $options['outputFile'] : ''); |
| 51 | + |
28 | 52 | /* |
29 | | - * You can acquire an OAuth 2.0 client ID and client secret from the |
| 53 | + * You can obtain an OAuth 2.0 client ID and client secret from the |
30 | 54 | * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}> |
31 | 55 | * For more information about using OAuth 2.0 to access Google APIs, please see: |
32 | 56 | * <https://developers.google.com/youtube/v3/guides/authentication> |
33 | 57 | * Please ensure that you have enabled the YouTube Data API for your project. |
34 | 58 | */ |
35 | | -$OAUTH2_CLIENT_ID = 'REPLACE_ME'; |
36 | | -$OAUTH2_CLIENT_SECRET = 'REPLACE_ME'; |
37 | | - |
38 | | -$client = new Google_Client(); |
39 | | -$client->setClientId($OAUTH2_CLIENT_ID); |
40 | | -$client->setClientSecret($OAUTH2_CLIENT_SECRET); |
41 | | - |
42 | | -/* |
43 | | - * This OAuth 2.0 access scope allows for full read/write access to the |
44 | | - * authenticated user's account. |
45 | | - */ |
46 | | -$client->setScopes('https://www.googleapis.com/auth/yt-analytics-monetary.readonly'); |
47 | | -$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'], |
48 | | - FILTER_SANITIZE_URL); |
49 | | -$client->setRedirectUri($redirect); |
50 | | - |
51 | | -// YouTube Reporting object used to make YouTube Reporting API requests. |
52 | | -$youtubeReporting = new Google_Service_YoutubeReporting($client); |
| 59 | +function getClient() { |
| 60 | + $client = new Google_Client(); |
| 61 | + $client->setAuthConfigFile('client_secrets_php.json'); |
| 62 | + $client->addScope( |
| 63 | + 'https://www.googleapis.com/auth/yt-analytics-monetary.readonly'); |
| 64 | + $client->setRedirectUri('urn:ietf:wg:oauth:2.0:oob'); |
| 65 | + $client->setAccessType('offline'); |
| 66 | + |
| 67 | + // Load previously authorized credentials from a file. |
| 68 | + $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH); |
| 69 | + if (file_exists($credentialsPath)) { |
| 70 | + $accessToken = json_decode(file_get_contents($credentialsPath), true); |
| 71 | + } else { |
| 72 | + // Request authorization from the user. |
| 73 | + $authUrl = $client->createAuthUrl(); |
| 74 | + printf('Open the following link in your browser:\n%s\n', $authUrl); |
| 75 | + print 'Enter verification code: '; |
| 76 | + $authCode = trim(fgets(STDIN)); |
| 77 | + |
| 78 | + // Exchange authorization code for an access token. |
| 79 | + $accessToken = $client->authenticate($authCode); |
| 80 | + $refreshToken = $client->getRefreshToken(); |
| 81 | + |
| 82 | + // Store the credentials to disk. |
| 83 | + if(!file_exists(dirname($credentialsPath))) { |
| 84 | + mkdir(dirname($credentialsPath), 0700, true); |
| 85 | + } |
| 86 | + file_put_contents($credentialsPath, json_encode($accessToken)); |
| 87 | + printf('Credentials saved to %s\n', $credentialsPath); |
53 | 88 |
|
54 | | -// Check if an auth token exists for the required scopes |
55 | | -$tokenSessionKey = 'token-' . $client->prepareScopes(); |
56 | | -if (isset($_GET['code'])) { |
57 | | - if (strval($_SESSION['state']) !== strval($_GET['state'])) { |
58 | | - die('The session state did not match.'); |
| 89 | + //fclose($fp); |
59 | 90 | } |
| 91 | + $client->setAccessToken($accessToken); |
60 | 92 |
|
61 | | - $client->authenticate($_GET['code']); |
62 | | - $_SESSION[$tokenSessionKey] = $client->getAccessToken(); |
63 | | - header('Location: ' . $redirect); |
64 | | -} |
| 93 | + // Refresh the token if it's expired. |
| 94 | + if ($client->isAccessTokenExpired()) { |
| 95 | + $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); |
| 96 | + file_put_contents($credentialsPath, json_encode($client->getAccessToken())); |
| 97 | + } |
65 | 98 |
|
66 | | -if (isset($_SESSION[$tokenSessionKey])) { |
67 | | - $client->setAccessToken($_SESSION[$tokenSessionKey]); |
| 99 | + return $client; |
68 | 100 | } |
69 | 101 |
|
70 | | -// Check to ensure that the access token was successfully acquired. |
71 | | -if ($client->getAccessToken()) { |
72 | | - $htmlBody = ''; |
73 | | - try { |
74 | | - if (empty(listReportingJobs($youtubeReporting, $htmlBody))) { |
75 | | - $htmlBody .= sprintf('<p>No jobs found.</p>'); |
76 | | - } else if ($_GET['reportUrl']){ |
77 | | - downloadReport($youtubeReporting, $_GET['reportUrl'], $htmlBody); |
78 | | - } else if ($_GET['jobId']){ |
79 | | - retrieveReports($youtubeReporting, $_GET['jobId'], $htmlBody); |
80 | | - } |
81 | | - } catch (Google_Service_Exception $e) { |
82 | | - $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>', |
83 | | - htmlspecialchars($e->getMessage())); |
84 | | - } catch (Google_Exception $e) { |
85 | | - $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>', |
86 | | - htmlspecialchars($e->getMessage())); |
| 102 | +/** |
| 103 | + * Expands the home directory alias '~' to the full path. |
| 104 | + * @param string $path the path to expand. |
| 105 | + * @return string the expanded path. |
| 106 | + */ |
| 107 | +function expandHomeDirectory($path) { |
| 108 | + $homeDirectory = getenv('HOME'); |
| 109 | + if (empty($homeDirectory)) { |
| 110 | + $homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH'); |
87 | 111 | } |
88 | | - $_SESSION[$tokenSessionKey] = $client->getAccessToken(); |
89 | | -} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') { |
90 | | - $htmlBody = <<<END |
91 | | - <h3>Client Credentials Required</h3> |
92 | | - <p> |
93 | | - You need to set <code>\$OAUTH2_CLIENT_ID</code> and |
94 | | - <code>\$OAUTH2_CLIENT_ID</code> before proceeding. |
95 | | - <p> |
96 | | -END; |
97 | | -} else { |
98 | | - // If the user hasn't authorized the app, initiate the OAuth flow |
99 | | - $state = mt_rand(); |
100 | | - $client->setState($state); |
101 | | - $_SESSION['state'] = $state; |
102 | | - |
103 | | - $authUrl = $client->createAuthUrl(); |
104 | | - $htmlBody = <<<END |
105 | | - <h3>Authorization Required</h3> |
106 | | - <p>You need to <a href="$authUrl">authorize access</a> before proceeding.<p> |
107 | | -END; |
| 112 | + return str_replace('~', realpath($homeDirectory), $path); |
108 | 113 | } |
109 | 114 |
|
110 | | - |
111 | 115 | /** |
112 | 116 | * Returns a list of reporting jobs. (jobs.listJobs) |
113 | 117 | * |
114 | 118 | * @param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object. |
115 | | - * @param $htmlBody - html body. |
| 119 | + * @param string $onBehalfOfContentOwner A content owner ID. |
116 | 120 | */ |
117 | | -function listReportingJobs(Google_Service_YouTubeReporting $youtubeReporting, &$htmlBody) { |
118 | | - // Call the YouTube Reporting API's jobs.list method to retrieve reporting jobs. |
119 | | - $reportingJobs = $youtubeReporting->jobs->listJobs(); |
120 | | - |
121 | | - $htmlBody .= "<h3>Reporting Jobs</h3><ul>"; |
| 121 | +function listReportingJobs(Google_Service_YouTubeReporting $youtubeReporting, |
| 122 | + $onBehalfOfContentOwner = '', $includeSystemManaged = False) { |
| 123 | + $reportingJobs = $youtubeReporting->jobs->listJobs( |
| 124 | + array('onBehalfOfContentOwner' => $onBehalfOfContentOwner, |
| 125 | + 'includeSystemManaged' => $includeSystemManaged)); |
| 126 | + print ('REPORTING JOBS' . PHP_EOL . '**************' . PHP_EOL); |
122 | 127 | foreach ($reportingJobs as $job) { |
123 | | - $htmlBody .= sprintf('<li>id: "%s", name: "%s" report type: "%s"</li>', $job['id'], |
124 | | - $job['name'], $job['reportTypeId']); |
| 128 | + print($job['reportTypeId'] . ':' . $job['id'] . PHP_EOL); |
125 | 129 | } |
126 | | - $htmlBody .= '</ul>'; |
127 | | - |
128 | | - return $reportingJobs; |
| 130 | + print(PHP_EOL); |
129 | 131 | } |
130 | 132 |
|
131 | | - |
132 | 133 | /** |
133 | 134 | * Lists reports created by a specific job. (reports.listJobsReports) |
134 | 135 | * |
135 | 136 | * @param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object. |
136 | 137 | * @param string $jobId The ID of the job. |
137 | | - * @param $htmlBody - html body. |
| 138 | + * @param string $onBehalfOfContentOwner A content owner ID. |
138 | 139 | */ |
139 | | -function retrieveReports(Google_Service_YouTubeReporting $youtubeReporting, $jobId, &$htmlBody) { |
140 | | - // Call the YouTube Reporting API's reports.list method to retrieve reports created by a job. |
141 | | - $reports = $youtubeReporting->jobs_reports->listJobsReports($jobId); |
142 | | - |
143 | | - if (empty($reports)) { |
144 | | - $htmlBody .= sprintf('<p>No reports found.</p>'); |
145 | | - } else { |
146 | | - $htmlBody .= sprintf('<h2>Reports for the job "%s"</h2><ul>', $jobId); |
147 | | - foreach ($reports as $report) { |
148 | | - $htmlBody .= sprintf('<li>From "%s" to "%s" downloadable at "%s"</li>', |
149 | | - $report['startTime'], $report['endTime'], $report['downloadUrl']); |
150 | | - $htmlBody .= '</ul>'; |
151 | | - } |
| 140 | +function listReportsForJob(Google_Service_YouTubeReporting $youtubeReporting, |
| 141 | + $jobId, $onBehalfOfContentOwner = '') { |
| 142 | + $reports = $youtubeReporting->jobs_reports->listJobsReports($jobId, |
| 143 | + array('onBehalfOfContentOwner' => $onBehalfOfContentOwner)); |
| 144 | + print ('DOWNLOADABLE REPORTS' . PHP_EOL . '********************' . PHP_EOL); |
| 145 | + foreach ($reports['reports'] as $report) { |
| 146 | + print('Created: ' . date('d M Y', strtotime($report['createTime'])) . |
| 147 | + ' (' . date('d M Y', strtotime($report['startTime'])) . |
| 148 | + ' to ' . date('d M Y', strtotime($report['endTime'])) . ')' . |
| 149 | + PHP_EOL . ' ' . $report['downloadUrl'] . PHP_EOL . PHP_EOL); |
152 | 150 | } |
153 | 151 | } |
154 | 152 |
|
155 | | - |
156 | 153 | /** |
157 | 154 | * Download the report specified by the URL. (media.download) |
158 | 155 | * |
159 | 156 | * @param Google_Service_YouTubereporting $youtubeReporting YouTube Reporting service object. |
160 | 157 | * @param string $reportUrl The URL of the report to be downloaded. |
| 158 | + * @param string $outputFile The file to write the report to locally. |
161 | 159 | * @param $htmlBody - html body. |
162 | 160 | */ |
163 | | -function downloadReport(Google_Service_YouTubeReporting $youtubeReporting, $reportUrl, &$htmlBody) { |
| 161 | +function downloadReport(Google_Service_YouTubeReporting $youtubeReporting, |
| 162 | + $reportUrl, $outputFile) { |
164 | 163 | $client = $youtubeReporting->getClient(); |
165 | | - // Setting the defer flag to true tells the client to return a request which can be called |
166 | | - // with ->execute(); instead of making the API call immediately. |
| 164 | + // Setting the defer flag to true tells the client to return a request that |
| 165 | + // can be called with ->execute(); instead of making the API call immediately. |
167 | 166 | $client->setDefer(true); |
168 | 167 |
|
169 | | - // Call the YouTube Reporting API's media.download method to download a report. |
170 | | - $request = $youtubeReporting->media->download("", array("alt" => "media")); |
| 168 | + // Call YouTube Reporting API's media.download method to download a report. |
| 169 | + $request = $youtubeReporting->media->download('', array('alt' => 'media')); |
171 | 170 | $request = $request->withUri(new \GuzzleHttp\Psr7\Uri($reportUrl)); |
172 | | - $response = $client->execute($request); |
173 | | - |
174 | | - file_put_contents("reportFile", $response->getBody()); |
| 171 | + $responseBody = ''; |
| 172 | + try { |
| 173 | + $response = $client->execute($request); |
| 174 | + $responseBody = $response->getBody(); |
| 175 | + } catch (Google_Service_Exception $e) { |
| 176 | + $responseBody = $e->getTrace()[0]['args'][0]->getResponseBody(); |
| 177 | + } |
| 178 | + file_put_contents($outputFile, $responseBody); |
175 | 179 | $client->setDefer(false); |
176 | 180 | } |
177 | | -?> |
178 | 181 |
|
179 | | -<!doctype html> |
180 | | -<html> |
181 | | -<head> |
182 | | -<title>Retrieve reports</title> |
183 | | -</head> |
184 | | -<body> |
185 | | - <form method="GET"> |
186 | | - <div> |
187 | | - Job Id: <input type="text" id="jobId" name="jobId" placeholder="Enter Job Id"> |
188 | | - </div> |
189 | | - <br> |
190 | | - <div> |
191 | | - Report URL: <input type="text" id="reportUrl" name="reportUrl" placeholder="Enter Report Url"> |
192 | | - </div> |
193 | | - <br> <input type="submit" value="Retrieve!"> |
194 | | - </form> |
195 | | - <?=$htmlBody?> |
196 | | -</body> |
197 | | -</html> |
| 182 | +// Define an object that will be used to make all API requests. |
| 183 | +$client = getClient(); |
| 184 | +// YouTube Reporting object used to make YouTube Reporting API requests. |
| 185 | +$youtubeReporting = new Google_Service_YouTubeReporting($client); |
| 186 | + |
| 187 | +if ($CONTENT_OWNER_ID) { |
| 188 | + if (!$DOWNLOAD_URL && !$JOB_ID) { |
| 189 | + listReportingJobs($youtubeReporting, $CONTENT_OWNER_ID, |
| 190 | + $INCLUDE_SYSTEM_MANAGED); |
| 191 | + } else if ($JOB_ID) { |
| 192 | + listReportsForJob($youtubeReporting, $JOB_ID, $CONTENT_OWNER_ID); |
| 193 | + } else if ($DOWNLOAD_URL && $OUTPUT_FILE) { |
| 194 | + downloadReport($youtubeReporting, $DOWNLOAD_URL, $OUTPUT_FILE); |
| 195 | + } |
| 196 | +} |
| 197 | + |
| 198 | +?> |
0 commit comments