| @ -0,0 +1,2 @@ | |||
| local: .env.local | |||
| prod: .env.prod | |||
| @ -0,0 +1,7 @@ | |||
| <?php | |||
| return [ | |||
| '*' => [ // Applies to all | |||
| 'APP_ENV' => 'local', | |||
| ], | |||
| ]; | |||
| @ -0,0 +1,71 @@ | |||
| <?php | |||
| namespace App\Http\Controllers; | |||
| use Google\ApiCore\ApiException; | |||
| use Google\Photos\Library\V1\PhotosLibraryClient; | |||
| use Illuminate\Http\Request; | |||
| class GooglePhotoController extends Controller { | |||
| public function connect(Request $request) | |||
| { | |||
| connectWithGooglePhotos($request, | |||
| ['https://www.googleapis.com/auth/photoslibrary'], | |||
| config('app.albums_authentication_redirect_url') | |||
| ); | |||
| } | |||
| public function index() | |||
| { | |||
| $credentials = session("credentials"); | |||
| if ($credentials == null || $credentials == "") { | |||
| return view("albums/connect"); | |||
| } | |||
| $photosLibraryClient = new PhotosLibraryClient(['credentials' => $credentials]); | |||
| try { | |||
| // $options['proxy'] = 'http://127.0.0.1:1087'; | |||
| // $pagedResponse = $photosLibraryClient->listAlbums(); | |||
| // $options['pageSize'] = 5; | |||
| $pagedResponse = $photosLibraryClient->listMediaItems(); | |||
| // echo 111; | |||
| // var_dump($pagedResponse->iterateAllElements());exit; | |||
| $iterator = $pagedResponse->iterateAllElements(); | |||
| $albums = []; | |||
| $yccImages = []; | |||
| while (true) { | |||
| for ($i = 0; $i < 100; $i++) { | |||
| $album = $iterator->current(); | |||
| if (strstr($album->getFilename(), "ycc")) { | |||
| $yccImages[] = $album->getId(); | |||
| } | |||
| $iterator->next(); | |||
| } | |||
| if (count($yccImages) > 1) { | |||
| $photosLibraryClient->batchAddMediaItemsToAlbum("AN5jk26M4hJ-wxLPKSzIDyjruMMkWjlDlVkgNaWWk3d3c7TGhm1vKU-YM0JhfgK5CfcfneoIx_8E", $yccImages); | |||
| echo "add " . count($yccImages) . " images to ycc\n"; | |||
| $yccImages = []; | |||
| } | |||
| break; | |||
| } | |||
| //// echo $album->getProductUrl(); | |||
| // $albums[] = $album; | |||
| // $iterator->next(); | |||
| // } | |||
| // exit; | |||
| // By using iterateAllElements, pagination is handled for us. | |||
| return view("albums.index", ['albums' => $pagedResponse->iterateAllElements()]); | |||
| // echo $templates->render( | |||
| // 'albums::index', | |||
| // ['albums' => $pagedResponse->iterateAllElements()]); | |||
| // echo $templates->render( | |||
| // 'albums::index', | |||
| // ['mediaItems' => $albums] | |||
| // ); | |||
| // ); | |||
| } catch (ApiException $e) { | |||
| // echo $templates->render('error', ['exception' => $e]); | |||
| view("error"); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,66 @@ | |||
| <?php | |||
| use Google\Auth\Credentials\UserRefreshCredentials; | |||
| use Google\Auth\HttpHandler\Guzzle7HttpHandler; | |||
| use Google\Auth\OAuth2; | |||
| use GuzzleHttp\Client; | |||
| function connectWithGooglePhotos($request, array $scopes, $redirectURI) | |||
| { | |||
| $clientSecretJson = json_decode( | |||
| file_get_contents('client_secret_1000190146810-j9mohjt8m4m8j8sj6hupl1bghp6o1pdn.apps.googleusercontent.com.json'), | |||
| true | |||
| )['web']; | |||
| // dump($clientSecretJson);exit; | |||
| $clientId = $clientSecretJson['client_id']; | |||
| $clientSecret = $clientSecretJson['client_secret']; | |||
| $oauth2 = new OAuth2([ | |||
| 'clientId' => $clientId, | |||
| 'clientSecret' => $clientSecret, | |||
| 'authorizationUri' => 'https://accounts.google.com/o/oauth2/v2/auth', | |||
| // Where to return the user to if they accept your request to access their account. | |||
| // You must authorize this URI in the Google API Console. | |||
| 'redirectUri' => $redirectURI, | |||
| 'tokenCredentialUri' => 'https://www.googleapis.com/oauth2/v4/token', | |||
| 'scope' => $scopes, | |||
| 'expiry' => \Google\Auth\OAuth2::DEFAULT_EXPIRY_SECONDS *24 | |||
| ]); | |||
| $client = new Client(['proxy' => 'http://127.0.0.1:1087']); | |||
| $httpHandler = new Guzzle7HttpHandler($client); | |||
| // The authorization URI will, upon redirecting, return a parameter called code. | |||
| $code = $request->get('code'); | |||
| if ($code == null || $code == "") { | |||
| $authenticationUrl = $oauth2->buildFullAuthorizationUri(['access_type' => 'offline']); | |||
| // dump($authenticationUrl); | |||
| // redirect($authenticationUrl); | |||
| header("Location: " . $authenticationUrl); | |||
| // redirect()->to($authenticationUrl); | |||
| } else { | |||
| dump("code is " . $code); | |||
| // With the code returned by the OAuth flow, we can retrieve the refresh token. | |||
| $oauth2->setCode($code); | |||
| $authToken = $oauth2->fetchAuthToken(); | |||
| $refreshToken = $authToken['access_token']; | |||
| // The UserRefreshCredentials will use the refresh token to 'refresh' the credentials when | |||
| // they expire. | |||
| $credentials = new UserRefreshCredentials( | |||
| $scopes, | |||
| [ | |||
| 'client_id' => $clientId, | |||
| 'client_secret' => $clientSecret, | |||
| 'refresh_token' => $refreshToken | |||
| ] | |||
| ); | |||
| session(['credentials' => $credentials]); | |||
| // Return the user to the home page. | |||
| dump("before redirect"); | |||
| redirect('google/home/index'); | |||
| // header("Location: index.php"); | |||
| } | |||
| } | |||
| @ -0,0 +1 @@ | |||
| {"web":{"client_id":"1000190146810-j9mohjt8m4m8j8sj6hupl1bghp6o1pdn.apps.googleusercontent.com","project_id":"photo1-1584853697553","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"oSPGIFy-Z_z92IG9iT03Dhor","redirect_uris":["http://localhost:8080/oauth2callback","http://localhost:1234/albums/connect.php","http://localhost:1234/filters/connect.php","https://ins.app/google/photo/connect"]}} | |||
| @ -0,0 +1 @@ | |||
| {"web":{"client_id":"1000190146810-j9mohjt8m4m8j8sj6hupl1bghp6o1pdn.apps.googleusercontent.com","project_id":"photo1-1584853697553","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"oSPGIFy-Z_z92IG9iT03Dhor","redirect_uris":["http://localhost:8080/oauth2callback","http://localhost:1234/albums/connect.php","http://localhost:1234/filters/connect.php","https://ins.app/google/photo/connect"]}} | |||
| @ -0,0 +1 @@ | |||
| {"web":{"client_id":"1000190146810-j9mohjt8m4m8j8sj6hupl1bghp6o1pdn.apps.googleusercontent.com","project_id":"photo1-1584853697553","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"oSPGIFy-Z_z92IG9iT03Dhor","redirect_uris":["http://localhost:8080/oauth2callback","http://localhost:1234/albums/connect.php","http://localhost:1234/filters/connect.php","https://ins.app/google/photo/connect","http://localhost:1234/google/photo/connect"]}} | |||
| @ -0,0 +1,4 @@ | |||
| { | |||
| "/js/app.js": "/js/app.js", | |||
| "/css/app.css": "/css/app.css" | |||
| } | |||
| @ -1,33 +1,16 @@ | |||
| /** | |||
| * First we will load all of this project's JavaScript dependencies which | |||
| * includes Vue and other libraries. It is a great starting point when | |||
| * building robust, powerful web applications using Vue and Laravel. | |||
| * includes React and other helpers. It's a great starting point while | |||
| * building robust, powerful web applications using React + Laravel. | |||
| */ | |||
| require('./bootstrap'); | |||
| window.Vue = require('vue'); | |||
| /** | |||
| * The following block of code may be used to automatically register your | |||
| * Vue components. It will recursively scan this directory for the Vue | |||
| * components and automatically register them with their "basename". | |||
| * | |||
| * Eg. ./components/ExampleComponent.vue -> <example-component></example-component> | |||
| */ | |||
| // const files = require.context('./', true, /\.vue$/i) | |||
| // files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default)) | |||
| Vue.component('example-component', require('./components/ExampleComponent.vue').default); | |||
| /** | |||
| * Next, we will create a fresh Vue application instance and attach it to | |||
| * Next, we will create a fresh React component instance and attach it to | |||
| * the page. Then, you may begin adding components to this application | |||
| * or customize the JavaScript scaffolding to fit your unique needs. | |||
| */ | |||
| const app = new Vue({ | |||
| el: '#app' | |||
| }); | |||
| require('./components/Example'); | |||
| @ -0,0 +1,26 @@ | |||
| import React, { Component } from 'react'; | |||
| import ReactDOM from 'react-dom'; | |||
| export default class Example extends Component { | |||
| render() { | |||
| return ( | |||
| <div className="container"> | |||
| <div className="row justify-content-center"> | |||
| <div className="col-md-8"> | |||
| <div className="card"> | |||
| <div className="card-header">Example Component</div> | |||
| <div className="card-body"> | |||
| I'm an example component! | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| ); | |||
| } | |||
| } | |||
| if (document.getElementById('example')) { | |||
| ReactDOM.render(<Example />, document.getElementById('example')); | |||
| } | |||
| @ -1,23 +0,0 @@ | |||
| <template> | |||
| <div class="container"> | |||
| <div class="row justify-content-center"> | |||
| <div class="col-md-8"> | |||
| <div class="card card-default"> | |||
| <div class="card-header">Example Component</div> | |||
| <div class="card-body"> | |||
| I'm an example component. | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| mounted() { | |||
| console.log('Component mounted.') | |||
| } | |||
| } | |||
| </script> | |||
| @ -0,0 +1,36 @@ | |||
| <?php | |||
| /** | |||
| * Copyright 2018 Google LLC | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * https://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| //$this->layout('template', ['title' => 'Connect with Google Photos']) | |||
| ?> | |||
| <div id="intro"> | |||
| <h4>Google Photos Library API sample</h4> | |||
| <img src="http://www.baidu.com" alt=""> | |||
| <h2>Title</h2> | |||
| <p>This sample will cover</p> | |||
| <ul> | |||
| <li>Connecting to a Google Photos Library</li> | |||
| <li>Requesting scopes from a Google Photos user</li> | |||
| <li>Read the entire library</li> | |||
| <li>Apply filters to a library</li> | |||
| </ul> | |||
| <a class="connect-btn" href="/google/photo/connect"> | |||
| <img src="../common/google_photos_logo.png"> | |||
| Connect to Google Photos | |||
| </a> | |||
| </div> | |||
| @ -0,0 +1,62 @@ | |||
| <?php | |||
| /** | |||
| * Copyright 2018 Google LLC | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * https://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| //$this->layout('template', ['title' => 'Photos Library API PHP Sample', 'additionalStylesheets' => ['views/style.css']]) | |||
| <dialog class="mdl-dialog"> | |||
| <h4 class="mdl-dialog__title">Create a new album</h4> | |||
| <form action="album.php"> | |||
| <div class="mdl-dialog__content"> | |||
| <div class="mdl-textfield mdl-js-textfield"> | |||
| <input type="text" class="mdl-textfield__input" name="create" id="create"/> | |||
| <label for="create" class="mdl-textfield__label">Title</label> | |||
| </div> | |||
| </div> | |||
| <div class="mdl-dialog__actions"> | |||
| <button class="mdl-button">Create</button> | |||
| <a class="mdl-button close">Cancel</a> | |||
| </div> | |||
| </form> | |||
| </dialog> | |||
| <div class="mdl-grid"> | |||
| <div class="mdl-cell mdl-cell--12-col description"> | |||
| <h3>This is your Google Photos library</h3> | |||
| <p>You've used the <span class="code">photoslibrary</span> scope to view the albums in the | |||
| user's library.</p> | |||
| <p>Use the create action to add a new album.</p> | |||
| <button id='create-btn' class="mdl-button mdl-button--raised mdl-button--colored">Create</button> | |||
| </div> | |||
| <?php $this->insert('album_grid', ['albums' => $albums, 'photoLink' => 'album.php']);?> | |||
| <!-- --><?php //$this->insert('image_grid', ['mediaItems' => $mediaItems]); ?> | |||
| </div> | |||
| <script> | |||
| var dialog = document.querySelector('dialog'); | |||
| var showModalButton = document.querySelector('#create-btn'); | |||
| showModalButton.addEventListener('click', function() { | |||
| dialog.showModal(); | |||
| }); | |||
| dialog.querySelector('.close').addEventListener('click', function() { | |||
| dialog.close(); | |||
| }); | |||
| </script> | |||