├── .gitignore ├── classes ├── Init.php └── Meet.php ├── composer.json ├── composer.lock ├── credentials └── .gitignore ├── index-raw.php ├── index.php ├── static └── style.css └── views └── view.php /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | vendor/ -------------------------------------------------------------------------------- /classes/Init.php: -------------------------------------------------------------------------------- 1 | meet = new Meet; 10 | } 11 | 12 | public function start() { 13 | // Save token if the request comes from google 14 | $this->saveToken(); 15 | 16 | // Save credential if upload file exists 17 | $this->saveCredential(); 18 | 19 | // CRUD 20 | $this->CRUDOperation(); 21 | 22 | return $this->meet; 23 | } 24 | 25 | public function saveToken() { 26 | if(isset($_GET['code'])) { 27 | $this->meet->saveToken($_GET['code']); 28 | header('Location: '.ROOT_URL); 29 | exit; 30 | } 31 | } 32 | 33 | public function saveCredential(){ 34 | if(isset($_FILES['credential']) && $_FILES['credential']['error']==0) { 35 | 36 | // Save credential file if exist and no error 37 | $this->meet->saveCredential($_FILES['credential']); 38 | 39 | header('Location: '.ROOT_URL); 40 | exit; 41 | } 42 | } 43 | 44 | public function CRUDOperation() { 45 | if(isset($_GET['action'])) { 46 | $now = time(); 47 | $start_time = rand($now+86400, $now+(86400*6)); 48 | $end_time = $start_time+3600; 49 | 50 | switch($_GET['action']) { 51 | case 'create' : 52 | $this->meet->createMeeting(array( 53 | 'title' => 'Title New ' . microtime(true), 54 | 'description' => 'Description New ' . microtime(true), 55 | 'start' => date("Y-m-d H:i:s", $start_time), 56 | 'end' => date("Y-m-d H:i:s", $end_time), 57 | 'timezone' => 'America/Los_Angeles' 58 | )); 59 | break; 60 | 61 | case 'delete' : 62 | $this->meet->deleteMeeting($_GET['id']); 63 | break; 64 | 65 | case 'update' : 66 | $this->meet->updateMeeting($_GET['id'], array( 67 | 'title' => 'Title Update ' . microtime(true), 68 | 'description' => 'Description Update ' . microtime(true), 69 | 'start' => date("Y-m-d H:i:s", $start_time), 70 | 'end' => date("Y-m-d H:i:s", $end_time), 71 | 'timezone' => 'America/Los_Angeles' 72 | )); 73 | break; 74 | } 75 | 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /classes/Meet.php: -------------------------------------------------------------------------------- 1 | current_calendar = $current_calendar; 23 | 24 | $this->credential_path = CREDENTIAL_PATH . '/credential.json'; 25 | $this->token_path = CREDENTIAL_PATH . '/token.json'; 26 | $this->google_callback_url = ROOT_URL; 27 | 28 | if($this->isCredentialLoaded()) { 29 | $this->client = new Google_Client(); 30 | $this->client->setApplicationName($this->app_name); 31 | $this->client->setAuthConfig($this->credential_path); 32 | $this->client->setRedirectUri($this->google_callback_url); 33 | $this->client->addScope($this->required_scopes); 34 | $this->client->setAccessType("offline"); 35 | $this->client->setApprovalPrompt('force'); 36 | $assigned = !($this->assignTokenToClient()===false); 37 | 38 | if($assigned) { 39 | // Create service if the token assigned 40 | $this->service = new Google_Service_Calendar($this->client); 41 | } 42 | } 43 | } 44 | 45 | // Return consent screen url 46 | public function get_consent_screen_url(){ 47 | return $this->client->createAuthUrl(); 48 | } 49 | 50 | // Upload credential file 51 | public function saveCredential($file){ 52 | move_uploaded_file($file['tmp_name'], $this->credential_path); 53 | } 54 | 55 | // Check if credential file uploaded 56 | public function isCredentialLoaded(){ 57 | return file_exists($this->credential_path); 58 | } 59 | 60 | // Assign the existing token, or try to refresh if expired. 61 | public function assignTokenToClient(){ 62 | 63 | if (file_exists($this->token_path)) { 64 | $accessToken = json_decode(file_get_contents($this->token_path), true); 65 | $this->client->setAccessToken($accessToken); 66 | } 67 | 68 | // Check if token expired 69 | if ($this->client->isAccessTokenExpired()) { 70 | 71 | $refresh_token = $this->client->getRefreshToken(); 72 | 73 | if(!$refresh_token){ 74 | return false; 75 | } 76 | 77 | $new_token = null; 78 | 79 | try { 80 | $new_token = $this->client->fetchAccessTokenWithRefreshToken($refresh_token); 81 | } catch(\Exception $e) { 82 | if($e) { 83 | return false; 84 | } 85 | } 86 | 87 | $this->saveToken(null, $new_token); 88 | } 89 | } 90 | 91 | 92 | // Save token provided by google 93 | public function saveToken($code=null, $token=null){ 94 | 95 | if(!$token){ 96 | $token = $this->client->fetchAccessTokenWithAuthCode($code); 97 | $this->client->setAccessToken($token); 98 | $token = $this->client->getAccessToken(); 99 | } 100 | 101 | file_put_contents($this->token_path, json_encode($token)); 102 | } 103 | 104 | 105 | // Check if the app is permitted by user via consent screen 106 | public function isAppPermitted(){ 107 | return $this->assignTokenToClient()===false ? false : true; 108 | } 109 | 110 | private function get_calendar_list($optParams=array()) { 111 | $list = array(); 112 | $calendarList = $this->service->calendarList->listCalendarList($optParams); 113 | $pageToken = $calendarList->getNextPageToken(); 114 | 115 | foreach ($calendarList->getItems() as $calendarListEntry) { 116 | $id = $calendarListEntry->getId(); 117 | $list[] = array( 118 | 'id' => $id, 119 | 'summary' => $calendarListEntry->getSummary() 120 | ); 121 | } 122 | 123 | if ($pageToken) { 124 | $optParams = array('pageToken' => $pageToken); 125 | $calendarList = $this->get_calendar_list($optParams); 126 | is_array($calendarList) ? $list = array_merge($list, $calendarList) : 0; 127 | } 128 | 129 | return $list; 130 | } 131 | 132 | public function getMeetingList() { 133 | 134 | $optParams = array( 135 | 'maxResults' => 50, 136 | 'orderBy' => 'startTime', 137 | 'singleEvents' => true, 138 | 'timeMin' => date('c'), 139 | ); 140 | 141 | $results = $this->service->events->listEvents($this->current_calendar, $optParams); 142 | $pageToken = $results->getNextPageToken(); 143 | $list = array(); 144 | 145 | foreach ($results->getItems() as $event) { 146 | $start = $event->start->dateTime; 147 | if (empty($start)) { 148 | $start = $event->start->date; 149 | } 150 | 151 | // var_dump($event); 152 | 153 | $id = $event->getId(); 154 | $list[] = array( 155 | 'id' => $id, 156 | 'title' => $event->getSummary(), 157 | 'start' => $start, 158 | 'meeting_link' => $event->hangoutLink 159 | ); 160 | } 161 | 162 | return $list; 163 | } 164 | 165 | public function createMeeting(array $payload) { 166 | 167 | // Prepare attendees array 168 | $attendees = isset($payload['attendees']) ? $payload['attendees'] : array(); 169 | $attendees = array_map(function($attendee){ 170 | return is_string($attendee) ? array('email' => $attendee) : $attendee; 171 | }, $attendees); 172 | 173 | // Mak the create request 174 | $event = new Google_Service_Calendar_Event(array( 175 | 'summary' => $payload['title'], 176 | 'description' => $payload['description'], 177 | 'start' => array( 178 | 'dateTime' => (new DateTime($payload['start']))->format('c'), 179 | 'timeZone' => (new DateTime($payload['timezone']))->format('c'), 180 | ), 181 | 'end' => array( 182 | 'dateTime' => (new DateTime($payload['end']))->format('c'), 183 | 'timeZone' => (new DateTime($payload['timezone']))->format('c'), 184 | ), 185 | 'attendees' => $attendees, 186 | 'conferenceData' => array( 187 | 'createRequest' => array( 188 | 'requestId' => 'meet_demo_' . microtime(true), 189 | ) 190 | ) 191 | )); 192 | 193 | $event = $this->service->events->insert($this->current_calendar, $event, array('conferenceDataVersion' => 1)); 194 | 195 | return array( 196 | 'event_id' => $event->getId(), 197 | 'event_link' => $event->htmlLink, 198 | 'conference_id' => $event->conferenceData->conferenceId, 199 | 'conference_link' => $event->hangoutLink, 200 | ); 201 | } 202 | 203 | public function deleteMeeting($event_id) { 204 | try { 205 | $this->service->events->delete($this->current_calendar, $event_id); 206 | } catch(\Exception $e) { 207 | 208 | } 209 | } 210 | 211 | public function updateMeeting($event_id, array $payload) { 212 | $event = $this->service->events->get($this->current_calendar, $event_id); 213 | 214 | foreach($payload as $key=>$value) { 215 | $key=='title' ? $key='summary' : 0; 216 | $method = 'set' . ucfirst($key); 217 | 218 | switch($key) { 219 | case 'summary' : 220 | case 'description' : 221 | $event->$method($value); 222 | break; 223 | 224 | case 'start' : 225 | case 'end' : 226 | $date_time = new Google_Service_Calendar_EventDateTime(); 227 | $date_time->setDateTime((new DateTime($value))->format('c')); 228 | $date_time->setTimeZone($payload['timezone']); 229 | $event->$method($date_time); 230 | break; 231 | } 232 | } 233 | 234 | $this->service->events->update($this->current_calendar, $event->getId(), $event); 235 | } 236 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google/meet", 3 | "type": "library", 4 | "description": "Google Meet Integration", 5 | "minimum-stability": "beta", 6 | "require": { 7 | "php": ">=5.4", 8 | "google/auth": "^1.10", 9 | "google/apiclient-services": "~0.13", 10 | "google/apiclient": "^2.10" 11 | }, 12 | "scripts": { 13 | "pre-autoload-dump": "Google\\Task\\Composer::cleanup" 14 | }, 15 | "extra": { 16 | "branch-alias": { 17 | "dev-master": "2.x-dev" 18 | }, 19 | "google/apiclient-services": [ 20 | "Calendar" 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "fcd41259b652075e21a4ddddf3395d4e", 8 | "packages": [ 9 | { 10 | "name": "firebase/php-jwt", 11 | "version": "v5.4.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/firebase/php-jwt.git", 15 | "reference": "d2113d9b2e0e349796e72d2a63cf9319100382d2" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d2113d9b2e0e349796e72d2a63cf9319100382d2", 20 | "reference": "d2113d9b2e0e349796e72d2a63cf9319100382d2", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": ">=4.8 <=9" 28 | }, 29 | "suggest": { 30 | "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" 31 | }, 32 | "type": "library", 33 | "autoload": { 34 | "psr-4": { 35 | "Firebase\\JWT\\": "src" 36 | } 37 | }, 38 | "notification-url": "https://packagist.org/downloads/", 39 | "license": [ 40 | "BSD-3-Clause" 41 | ], 42 | "authors": [ 43 | { 44 | "name": "Neuman Vong", 45 | "email": "neuman+pear@twilio.com", 46 | "role": "Developer" 47 | }, 48 | { 49 | "name": "Anant Narayanan", 50 | "email": "anant@php.net", 51 | "role": "Developer" 52 | } 53 | ], 54 | "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", 55 | "homepage": "https://github.com/firebase/php-jwt", 56 | "keywords": [ 57 | "jwt", 58 | "php" 59 | ], 60 | "support": { 61 | "issues": "https://github.com/firebase/php-jwt/issues", 62 | "source": "https://github.com/firebase/php-jwt/tree/v5.4.0" 63 | }, 64 | "time": "2021-06-23T19:00:23+00:00" 65 | }, 66 | { 67 | "name": "google/apiclient", 68 | "version": "v2.11.0", 69 | "source": { 70 | "type": "git", 71 | "url": "https://github.com/googleapis/google-api-php-client.git", 72 | "reference": "7db9eb40c8ba887e81c0fe84f2888a967396cdfb" 73 | }, 74 | "dist": { 75 | "type": "zip", 76 | "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/7db9eb40c8ba887e81c0fe84f2888a967396cdfb", 77 | "reference": "7db9eb40c8ba887e81c0fe84f2888a967396cdfb", 78 | "shasum": "" 79 | }, 80 | "require": { 81 | "firebase/php-jwt": "~2.0||~3.0||~4.0||~5.0", 82 | "google/apiclient-services": "~0.200", 83 | "google/auth": "^1.10", 84 | "guzzlehttp/guzzle": "~5.3.3||~6.0||~7.0", 85 | "guzzlehttp/psr7": "^1.7||^2.0.0", 86 | "monolog/monolog": "^1.17||^2.0", 87 | "php": "^5.6|^7.0|^8.0", 88 | "phpseclib/phpseclib": "~2.0||^3.0.2" 89 | }, 90 | "require-dev": { 91 | "cache/filesystem-adapter": "^0.3.2|^1.1", 92 | "composer/composer": "^1.10.22", 93 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7", 94 | "phpcompatibility/php-compatibility": "^9.2", 95 | "phpspec/prophecy-phpunit": "^1.1||^2.0", 96 | "phpunit/phpunit": "^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0", 97 | "squizlabs/php_codesniffer": "~2.3", 98 | "symfony/css-selector": "~2.1", 99 | "symfony/dom-crawler": "~2.1", 100 | "yoast/phpunit-polyfills": "^1.0" 101 | }, 102 | "suggest": { 103 | "cache/filesystem-adapter": "For caching certs and tokens (using Google\\Client::setCache)" 104 | }, 105 | "type": "library", 106 | "extra": { 107 | "branch-alias": { 108 | "dev-master": "2.x-dev" 109 | } 110 | }, 111 | "autoload": { 112 | "psr-4": { 113 | "Google\\": "src/" 114 | }, 115 | "files": [ 116 | "src/aliases.php" 117 | ], 118 | "classmap": [ 119 | "src/aliases.php" 120 | ] 121 | }, 122 | "notification-url": "https://packagist.org/downloads/", 123 | "license": [ 124 | "Apache-2.0" 125 | ], 126 | "description": "Client library for Google APIs", 127 | "homepage": "http://developers.google.com/api-client-library/php", 128 | "keywords": [ 129 | "google" 130 | ], 131 | "support": { 132 | "issues": "https://github.com/googleapis/google-api-php-client/issues", 133 | "source": "https://github.com/googleapis/google-api-php-client/tree/v2.11.0" 134 | }, 135 | "time": "2021-09-20T21:15:55+00:00" 136 | }, 137 | { 138 | "name": "google/apiclient-services", 139 | "version": "v0.213.0", 140 | "source": { 141 | "type": "git", 142 | "url": "https://github.com/googleapis/google-api-php-client-services.git", 143 | "reference": "260311821505438eb9208b068da0d849b8ea9baa" 144 | }, 145 | "dist": { 146 | "type": "zip", 147 | "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/260311821505438eb9208b068da0d849b8ea9baa", 148 | "reference": "260311821505438eb9208b068da0d849b8ea9baa", 149 | "shasum": "" 150 | }, 151 | "require": { 152 | "php": ">=5.6" 153 | }, 154 | "require-dev": { 155 | "phpunit/phpunit": "^5.7||^8.5.13" 156 | }, 157 | "type": "library", 158 | "autoload": { 159 | "psr-4": { 160 | "Google\\Service\\": "src" 161 | }, 162 | "files": [ 163 | "autoload.php" 164 | ] 165 | }, 166 | "notification-url": "https://packagist.org/downloads/", 167 | "license": [ 168 | "Apache-2.0" 169 | ], 170 | "description": "Client library for Google APIs", 171 | "homepage": "http://developers.google.com/api-client-library/php", 172 | "keywords": [ 173 | "google" 174 | ], 175 | "support": { 176 | "issues": "https://github.com/googleapis/google-api-php-client-services/issues", 177 | "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.213.0" 178 | }, 179 | "time": "2021-09-19T11:18:26+00:00" 180 | }, 181 | { 182 | "name": "google/auth", 183 | "version": "v1.18.0", 184 | "source": { 185 | "type": "git", 186 | "url": "https://github.com/googleapis/google-auth-library-php.git", 187 | "reference": "21dd478e77b0634ed9e3a68613f74ed250ca9347" 188 | }, 189 | "dist": { 190 | "type": "zip", 191 | "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/21dd478e77b0634ed9e3a68613f74ed250ca9347", 192 | "reference": "21dd478e77b0634ed9e3a68613f74ed250ca9347", 193 | "shasum": "" 194 | }, 195 | "require": { 196 | "firebase/php-jwt": "~2.0|~3.0|~4.0|~5.0", 197 | "guzzlehttp/guzzle": "^5.3.1|^6.2.1|^7.0", 198 | "guzzlehttp/psr7": "^1.7|^2.0", 199 | "php": ">=5.4", 200 | "psr/cache": "^1.0|^2.0", 201 | "psr/http-message": "^1.0" 202 | }, 203 | "require-dev": { 204 | "guzzlehttp/promises": "0.1.1|^1.3", 205 | "kelvinmo/simplejwt": "^0.2.5|^0.5.1", 206 | "phpseclib/phpseclib": "^2.0.31", 207 | "phpunit/phpunit": "^4.8.36|^5.7", 208 | "sebastian/comparator": ">=1.2.3" 209 | }, 210 | "suggest": { 211 | "phpseclib/phpseclib": "May be used in place of OpenSSL for signing strings or for token management. Please require version ^2." 212 | }, 213 | "type": "library", 214 | "autoload": { 215 | "psr-4": { 216 | "Google\\Auth\\": "src" 217 | } 218 | }, 219 | "notification-url": "https://packagist.org/downloads/", 220 | "license": [ 221 | "Apache-2.0" 222 | ], 223 | "description": "Google Auth Library for PHP", 224 | "homepage": "http://github.com/google/google-auth-library-php", 225 | "keywords": [ 226 | "Authentication", 227 | "google", 228 | "oauth2" 229 | ], 230 | "support": { 231 | "docs": "https://googleapis.github.io/google-auth-library-php/master/", 232 | "issues": "https://github.com/googleapis/google-auth-library-php/issues", 233 | "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.18.0" 234 | }, 235 | "time": "2021-08-24T18:03:18+00:00" 236 | }, 237 | { 238 | "name": "guzzlehttp/guzzle", 239 | "version": "7.3.0", 240 | "source": { 241 | "type": "git", 242 | "url": "https://github.com/guzzle/guzzle.git", 243 | "reference": "7008573787b430c1c1f650e3722d9bba59967628" 244 | }, 245 | "dist": { 246 | "type": "zip", 247 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", 248 | "reference": "7008573787b430c1c1f650e3722d9bba59967628", 249 | "shasum": "" 250 | }, 251 | "require": { 252 | "ext-json": "*", 253 | "guzzlehttp/promises": "^1.4", 254 | "guzzlehttp/psr7": "^1.7 || ^2.0", 255 | "php": "^7.2.5 || ^8.0", 256 | "psr/http-client": "^1.0" 257 | }, 258 | "provide": { 259 | "psr/http-client-implementation": "1.0" 260 | }, 261 | "require-dev": { 262 | "bamarni/composer-bin-plugin": "^1.4.1", 263 | "ext-curl": "*", 264 | "php-http/client-integration-tests": "^3.0", 265 | "phpunit/phpunit": "^8.5.5 || ^9.3.5", 266 | "psr/log": "^1.1" 267 | }, 268 | "suggest": { 269 | "ext-curl": "Required for CURL handler support", 270 | "ext-intl": "Required for Internationalized Domain Name (IDN) support", 271 | "psr/log": "Required for using the Log middleware" 272 | }, 273 | "type": "library", 274 | "extra": { 275 | "branch-alias": { 276 | "dev-master": "7.3-dev" 277 | } 278 | }, 279 | "autoload": { 280 | "psr-4": { 281 | "GuzzleHttp\\": "src/" 282 | }, 283 | "files": [ 284 | "src/functions_include.php" 285 | ] 286 | }, 287 | "notification-url": "https://packagist.org/downloads/", 288 | "license": [ 289 | "MIT" 290 | ], 291 | "authors": [ 292 | { 293 | "name": "Michael Dowling", 294 | "email": "mtdowling@gmail.com", 295 | "homepage": "https://github.com/mtdowling" 296 | }, 297 | { 298 | "name": "Márk Sági-Kazár", 299 | "email": "mark.sagikazar@gmail.com", 300 | "homepage": "https://sagikazarmark.hu" 301 | } 302 | ], 303 | "description": "Guzzle is a PHP HTTP client library", 304 | "homepage": "http://guzzlephp.org/", 305 | "keywords": [ 306 | "client", 307 | "curl", 308 | "framework", 309 | "http", 310 | "http client", 311 | "psr-18", 312 | "psr-7", 313 | "rest", 314 | "web service" 315 | ], 316 | "support": { 317 | "issues": "https://github.com/guzzle/guzzle/issues", 318 | "source": "https://github.com/guzzle/guzzle/tree/7.3.0" 319 | }, 320 | "funding": [ 321 | { 322 | "url": "https://github.com/GrahamCampbell", 323 | "type": "github" 324 | }, 325 | { 326 | "url": "https://github.com/Nyholm", 327 | "type": "github" 328 | }, 329 | { 330 | "url": "https://github.com/alexeyshockov", 331 | "type": "github" 332 | }, 333 | { 334 | "url": "https://github.com/gmponos", 335 | "type": "github" 336 | } 337 | ], 338 | "time": "2021-03-23T11:33:13+00:00" 339 | }, 340 | { 341 | "name": "guzzlehttp/promises", 342 | "version": "1.4.1", 343 | "source": { 344 | "type": "git", 345 | "url": "https://github.com/guzzle/promises.git", 346 | "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" 347 | }, 348 | "dist": { 349 | "type": "zip", 350 | "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", 351 | "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", 352 | "shasum": "" 353 | }, 354 | "require": { 355 | "php": ">=5.5" 356 | }, 357 | "require-dev": { 358 | "symfony/phpunit-bridge": "^4.4 || ^5.1" 359 | }, 360 | "type": "library", 361 | "extra": { 362 | "branch-alias": { 363 | "dev-master": "1.4-dev" 364 | } 365 | }, 366 | "autoload": { 367 | "psr-4": { 368 | "GuzzleHttp\\Promise\\": "src/" 369 | }, 370 | "files": [ 371 | "src/functions_include.php" 372 | ] 373 | }, 374 | "notification-url": "https://packagist.org/downloads/", 375 | "license": [ 376 | "MIT" 377 | ], 378 | "authors": [ 379 | { 380 | "name": "Michael Dowling", 381 | "email": "mtdowling@gmail.com", 382 | "homepage": "https://github.com/mtdowling" 383 | } 384 | ], 385 | "description": "Guzzle promises library", 386 | "keywords": [ 387 | "promise" 388 | ], 389 | "support": { 390 | "issues": "https://github.com/guzzle/promises/issues", 391 | "source": "https://github.com/guzzle/promises/tree/1.4.1" 392 | }, 393 | "time": "2021-03-07T09:25:29+00:00" 394 | }, 395 | { 396 | "name": "guzzlehttp/psr7", 397 | "version": "2.0.0", 398 | "source": { 399 | "type": "git", 400 | "url": "https://github.com/guzzle/psr7.git", 401 | "reference": "1dc8d9cba3897165e16d12bb13d813afb1eb3fe7" 402 | }, 403 | "dist": { 404 | "type": "zip", 405 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/1dc8d9cba3897165e16d12bb13d813afb1eb3fe7", 406 | "reference": "1dc8d9cba3897165e16d12bb13d813afb1eb3fe7", 407 | "shasum": "" 408 | }, 409 | "require": { 410 | "php": "^7.2.5 || ^8.0", 411 | "psr/http-factory": "^1.0", 412 | "psr/http-message": "^1.0", 413 | "ralouphie/getallheaders": "^3.0" 414 | }, 415 | "provide": { 416 | "psr/http-factory-implementation": "1.0", 417 | "psr/http-message-implementation": "1.0" 418 | }, 419 | "require-dev": { 420 | "bamarni/composer-bin-plugin": "^1.4.1", 421 | "http-interop/http-factory-tests": "^0.9", 422 | "phpunit/phpunit": "^8.5.8 || ^9.3.10" 423 | }, 424 | "suggest": { 425 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 426 | }, 427 | "type": "library", 428 | "extra": { 429 | "branch-alias": { 430 | "dev-master": "2.0-dev" 431 | } 432 | }, 433 | "autoload": { 434 | "psr-4": { 435 | "GuzzleHttp\\Psr7\\": "src/" 436 | } 437 | }, 438 | "notification-url": "https://packagist.org/downloads/", 439 | "license": [ 440 | "MIT" 441 | ], 442 | "authors": [ 443 | { 444 | "name": "Michael Dowling", 445 | "email": "mtdowling@gmail.com", 446 | "homepage": "https://github.com/mtdowling" 447 | }, 448 | { 449 | "name": "Tobias Schultze", 450 | "homepage": "https://github.com/Tobion" 451 | }, 452 | { 453 | "name": "Márk Sági-Kazár", 454 | "email": "mark.sagikazar@gmail.com", 455 | "homepage": "https://sagikazarmark.hu" 456 | } 457 | ], 458 | "description": "PSR-7 message implementation that also provides common utility methods", 459 | "keywords": [ 460 | "http", 461 | "message", 462 | "psr-7", 463 | "request", 464 | "response", 465 | "stream", 466 | "uri", 467 | "url" 468 | ], 469 | "support": { 470 | "issues": "https://github.com/guzzle/psr7/issues", 471 | "source": "https://github.com/guzzle/psr7/tree/2.0.0" 472 | }, 473 | "time": "2021-06-30T20:03:07+00:00" 474 | }, 475 | { 476 | "name": "monolog/monolog", 477 | "version": "2.3.4", 478 | "source": { 479 | "type": "git", 480 | "url": "https://github.com/Seldaek/monolog.git", 481 | "reference": "437e7a1c50044b92773b361af77620efb76fff59" 482 | }, 483 | "dist": { 484 | "type": "zip", 485 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/437e7a1c50044b92773b361af77620efb76fff59", 486 | "reference": "437e7a1c50044b92773b361af77620efb76fff59", 487 | "shasum": "" 488 | }, 489 | "require": { 490 | "php": ">=7.2", 491 | "psr/log": "^1.0.1 || ^2.0 || ^3.0" 492 | }, 493 | "provide": { 494 | "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" 495 | }, 496 | "require-dev": { 497 | "aws/aws-sdk-php": "^2.4.9 || ^3.0", 498 | "doctrine/couchdb": "~1.0@dev", 499 | "elasticsearch/elasticsearch": "^7", 500 | "graylog2/gelf-php": "^1.4.2", 501 | "mongodb/mongodb": "^1.8", 502 | "php-amqplib/php-amqplib": "~2.4", 503 | "php-console/php-console": "^3.1.3", 504 | "phpspec/prophecy": "^1.6.1", 505 | "phpstan/phpstan": "^0.12.91", 506 | "phpunit/phpunit": "^8.5", 507 | "predis/predis": "^1.1", 508 | "rollbar/rollbar": "^1.3", 509 | "ruflin/elastica": ">=0.90@dev", 510 | "swiftmailer/swiftmailer": "^5.3|^6.0" 511 | }, 512 | "suggest": { 513 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 514 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 515 | "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", 516 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 517 | "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", 518 | "ext-mbstring": "Allow to work properly with unicode symbols", 519 | "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", 520 | "ext-openssl": "Required to send log messages using SSL", 521 | "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", 522 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 523 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", 524 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 525 | "php-console/php-console": "Allow sending log messages to Google Chrome", 526 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 527 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server" 528 | }, 529 | "type": "library", 530 | "extra": { 531 | "branch-alias": { 532 | "dev-main": "2.x-dev" 533 | } 534 | }, 535 | "autoload": { 536 | "psr-4": { 537 | "Monolog\\": "src/Monolog" 538 | } 539 | }, 540 | "notification-url": "https://packagist.org/downloads/", 541 | "license": [ 542 | "MIT" 543 | ], 544 | "authors": [ 545 | { 546 | "name": "Jordi Boggiano", 547 | "email": "j.boggiano@seld.be", 548 | "homepage": "https://seld.be" 549 | } 550 | ], 551 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 552 | "homepage": "https://github.com/Seldaek/monolog", 553 | "keywords": [ 554 | "log", 555 | "logging", 556 | "psr-3" 557 | ], 558 | "support": { 559 | "issues": "https://github.com/Seldaek/monolog/issues", 560 | "source": "https://github.com/Seldaek/monolog/tree/2.3.4" 561 | }, 562 | "funding": [ 563 | { 564 | "url": "https://github.com/Seldaek", 565 | "type": "github" 566 | }, 567 | { 568 | "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", 569 | "type": "tidelift" 570 | } 571 | ], 572 | "time": "2021-09-15T11:27:21+00:00" 573 | }, 574 | { 575 | "name": "paragonie/constant_time_encoding", 576 | "version": "v2.4.0", 577 | "source": { 578 | "type": "git", 579 | "url": "https://github.com/paragonie/constant_time_encoding.git", 580 | "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c" 581 | }, 582 | "dist": { 583 | "type": "zip", 584 | "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c", 585 | "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c", 586 | "shasum": "" 587 | }, 588 | "require": { 589 | "php": "^7|^8" 590 | }, 591 | "require-dev": { 592 | "phpunit/phpunit": "^6|^7|^8|^9", 593 | "vimeo/psalm": "^1|^2|^3|^4" 594 | }, 595 | "type": "library", 596 | "autoload": { 597 | "psr-4": { 598 | "ParagonIE\\ConstantTime\\": "src/" 599 | } 600 | }, 601 | "notification-url": "https://packagist.org/downloads/", 602 | "license": [ 603 | "MIT" 604 | ], 605 | "authors": [ 606 | { 607 | "name": "Paragon Initiative Enterprises", 608 | "email": "security@paragonie.com", 609 | "homepage": "https://paragonie.com", 610 | "role": "Maintainer" 611 | }, 612 | { 613 | "name": "Steve 'Sc00bz' Thomas", 614 | "email": "steve@tobtu.com", 615 | "homepage": "https://www.tobtu.com", 616 | "role": "Original Developer" 617 | } 618 | ], 619 | "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", 620 | "keywords": [ 621 | "base16", 622 | "base32", 623 | "base32_decode", 624 | "base32_encode", 625 | "base64", 626 | "base64_decode", 627 | "base64_encode", 628 | "bin2hex", 629 | "encoding", 630 | "hex", 631 | "hex2bin", 632 | "rfc4648" 633 | ], 634 | "support": { 635 | "email": "info@paragonie.com", 636 | "issues": "https://github.com/paragonie/constant_time_encoding/issues", 637 | "source": "https://github.com/paragonie/constant_time_encoding" 638 | }, 639 | "time": "2020-12-06T15:14:20+00:00" 640 | }, 641 | { 642 | "name": "paragonie/random_compat", 643 | "version": "v9.99.100", 644 | "source": { 645 | "type": "git", 646 | "url": "https://github.com/paragonie/random_compat.git", 647 | "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" 648 | }, 649 | "dist": { 650 | "type": "zip", 651 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", 652 | "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", 653 | "shasum": "" 654 | }, 655 | "require": { 656 | "php": ">= 7" 657 | }, 658 | "require-dev": { 659 | "phpunit/phpunit": "4.*|5.*", 660 | "vimeo/psalm": "^1" 661 | }, 662 | "suggest": { 663 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 664 | }, 665 | "type": "library", 666 | "notification-url": "https://packagist.org/downloads/", 667 | "license": [ 668 | "MIT" 669 | ], 670 | "authors": [ 671 | { 672 | "name": "Paragon Initiative Enterprises", 673 | "email": "security@paragonie.com", 674 | "homepage": "https://paragonie.com" 675 | } 676 | ], 677 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 678 | "keywords": [ 679 | "csprng", 680 | "polyfill", 681 | "pseudorandom", 682 | "random" 683 | ], 684 | "support": { 685 | "email": "info@paragonie.com", 686 | "issues": "https://github.com/paragonie/random_compat/issues", 687 | "source": "https://github.com/paragonie/random_compat" 688 | }, 689 | "time": "2020-10-15T08:29:30+00:00" 690 | }, 691 | { 692 | "name": "phpseclib/phpseclib", 693 | "version": "3.0.10", 694 | "source": { 695 | "type": "git", 696 | "url": "https://github.com/phpseclib/phpseclib.git", 697 | "reference": "62fcc5a94ac83b1506f52d7558d828617fac9187" 698 | }, 699 | "dist": { 700 | "type": "zip", 701 | "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/62fcc5a94ac83b1506f52d7558d828617fac9187", 702 | "reference": "62fcc5a94ac83b1506f52d7558d828617fac9187", 703 | "shasum": "" 704 | }, 705 | "require": { 706 | "paragonie/constant_time_encoding": "^1|^2", 707 | "paragonie/random_compat": "^1.4|^2.0|^9.99.99", 708 | "php": ">=5.6.1" 709 | }, 710 | "require-dev": { 711 | "phing/phing": "~2.7", 712 | "phpunit/phpunit": "^5.7|^6.0|^9.4", 713 | "squizlabs/php_codesniffer": "~2.0" 714 | }, 715 | "suggest": { 716 | "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", 717 | "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", 718 | "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", 719 | "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." 720 | }, 721 | "type": "library", 722 | "autoload": { 723 | "files": [ 724 | "phpseclib/bootstrap.php" 725 | ], 726 | "psr-4": { 727 | "phpseclib3\\": "phpseclib/" 728 | } 729 | }, 730 | "notification-url": "https://packagist.org/downloads/", 731 | "license": [ 732 | "MIT" 733 | ], 734 | "authors": [ 735 | { 736 | "name": "Jim Wigginton", 737 | "email": "terrafrost@php.net", 738 | "role": "Lead Developer" 739 | }, 740 | { 741 | "name": "Patrick Monnerat", 742 | "email": "pm@datasphere.ch", 743 | "role": "Developer" 744 | }, 745 | { 746 | "name": "Andreas Fischer", 747 | "email": "bantu@phpbb.com", 748 | "role": "Developer" 749 | }, 750 | { 751 | "name": "Hans-Jürgen Petrich", 752 | "email": "petrich@tronic-media.com", 753 | "role": "Developer" 754 | }, 755 | { 756 | "name": "Graham Campbell", 757 | "email": "graham@alt-three.com", 758 | "role": "Developer" 759 | } 760 | ], 761 | "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", 762 | "homepage": "http://phpseclib.sourceforge.net", 763 | "keywords": [ 764 | "BigInteger", 765 | "aes", 766 | "asn.1", 767 | "asn1", 768 | "blowfish", 769 | "crypto", 770 | "cryptography", 771 | "encryption", 772 | "rsa", 773 | "security", 774 | "sftp", 775 | "signature", 776 | "signing", 777 | "ssh", 778 | "twofish", 779 | "x.509", 780 | "x509" 781 | ], 782 | "support": { 783 | "issues": "https://github.com/phpseclib/phpseclib/issues", 784 | "source": "https://github.com/phpseclib/phpseclib/tree/3.0.10" 785 | }, 786 | "funding": [ 787 | { 788 | "url": "https://github.com/terrafrost", 789 | "type": "github" 790 | }, 791 | { 792 | "url": "https://www.patreon.com/phpseclib", 793 | "type": "patreon" 794 | }, 795 | { 796 | "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", 797 | "type": "tidelift" 798 | } 799 | ], 800 | "time": "2021-08-16T04:24:45+00:00" 801 | }, 802 | { 803 | "name": "psr/cache", 804 | "version": "1.0.1", 805 | "source": { 806 | "type": "git", 807 | "url": "https://github.com/php-fig/cache.git", 808 | "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" 809 | }, 810 | "dist": { 811 | "type": "zip", 812 | "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", 813 | "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", 814 | "shasum": "" 815 | }, 816 | "require": { 817 | "php": ">=5.3.0" 818 | }, 819 | "type": "library", 820 | "extra": { 821 | "branch-alias": { 822 | "dev-master": "1.0.x-dev" 823 | } 824 | }, 825 | "autoload": { 826 | "psr-4": { 827 | "Psr\\Cache\\": "src/" 828 | } 829 | }, 830 | "notification-url": "https://packagist.org/downloads/", 831 | "license": [ 832 | "MIT" 833 | ], 834 | "authors": [ 835 | { 836 | "name": "PHP-FIG", 837 | "homepage": "http://www.php-fig.org/" 838 | } 839 | ], 840 | "description": "Common interface for caching libraries", 841 | "keywords": [ 842 | "cache", 843 | "psr", 844 | "psr-6" 845 | ], 846 | "support": { 847 | "source": "https://github.com/php-fig/cache/tree/master" 848 | }, 849 | "time": "2016-08-06T20:24:11+00:00" 850 | }, 851 | { 852 | "name": "psr/http-client", 853 | "version": "1.0.1", 854 | "source": { 855 | "type": "git", 856 | "url": "https://github.com/php-fig/http-client.git", 857 | "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" 858 | }, 859 | "dist": { 860 | "type": "zip", 861 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", 862 | "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", 863 | "shasum": "" 864 | }, 865 | "require": { 866 | "php": "^7.0 || ^8.0", 867 | "psr/http-message": "^1.0" 868 | }, 869 | "type": "library", 870 | "extra": { 871 | "branch-alias": { 872 | "dev-master": "1.0.x-dev" 873 | } 874 | }, 875 | "autoload": { 876 | "psr-4": { 877 | "Psr\\Http\\Client\\": "src/" 878 | } 879 | }, 880 | "notification-url": "https://packagist.org/downloads/", 881 | "license": [ 882 | "MIT" 883 | ], 884 | "authors": [ 885 | { 886 | "name": "PHP-FIG", 887 | "homepage": "http://www.php-fig.org/" 888 | } 889 | ], 890 | "description": "Common interface for HTTP clients", 891 | "homepage": "https://github.com/php-fig/http-client", 892 | "keywords": [ 893 | "http", 894 | "http-client", 895 | "psr", 896 | "psr-18" 897 | ], 898 | "support": { 899 | "source": "https://github.com/php-fig/http-client/tree/master" 900 | }, 901 | "time": "2020-06-29T06:28:15+00:00" 902 | }, 903 | { 904 | "name": "psr/http-factory", 905 | "version": "1.0.1", 906 | "source": { 907 | "type": "git", 908 | "url": "https://github.com/php-fig/http-factory.git", 909 | "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" 910 | }, 911 | "dist": { 912 | "type": "zip", 913 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", 914 | "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", 915 | "shasum": "" 916 | }, 917 | "require": { 918 | "php": ">=7.0.0", 919 | "psr/http-message": "^1.0" 920 | }, 921 | "type": "library", 922 | "extra": { 923 | "branch-alias": { 924 | "dev-master": "1.0.x-dev" 925 | } 926 | }, 927 | "autoload": { 928 | "psr-4": { 929 | "Psr\\Http\\Message\\": "src/" 930 | } 931 | }, 932 | "notification-url": "https://packagist.org/downloads/", 933 | "license": [ 934 | "MIT" 935 | ], 936 | "authors": [ 937 | { 938 | "name": "PHP-FIG", 939 | "homepage": "http://www.php-fig.org/" 940 | } 941 | ], 942 | "description": "Common interfaces for PSR-7 HTTP message factories", 943 | "keywords": [ 944 | "factory", 945 | "http", 946 | "message", 947 | "psr", 948 | "psr-17", 949 | "psr-7", 950 | "request", 951 | "response" 952 | ], 953 | "support": { 954 | "source": "https://github.com/php-fig/http-factory/tree/master" 955 | }, 956 | "time": "2019-04-30T12:38:16+00:00" 957 | }, 958 | { 959 | "name": "psr/http-message", 960 | "version": "1.0.1", 961 | "source": { 962 | "type": "git", 963 | "url": "https://github.com/php-fig/http-message.git", 964 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 965 | }, 966 | "dist": { 967 | "type": "zip", 968 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 969 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 970 | "shasum": "" 971 | }, 972 | "require": { 973 | "php": ">=5.3.0" 974 | }, 975 | "type": "library", 976 | "extra": { 977 | "branch-alias": { 978 | "dev-master": "1.0.x-dev" 979 | } 980 | }, 981 | "autoload": { 982 | "psr-4": { 983 | "Psr\\Http\\Message\\": "src/" 984 | } 985 | }, 986 | "notification-url": "https://packagist.org/downloads/", 987 | "license": [ 988 | "MIT" 989 | ], 990 | "authors": [ 991 | { 992 | "name": "PHP-FIG", 993 | "homepage": "http://www.php-fig.org/" 994 | } 995 | ], 996 | "description": "Common interface for HTTP messages", 997 | "homepage": "https://github.com/php-fig/http-message", 998 | "keywords": [ 999 | "http", 1000 | "http-message", 1001 | "psr", 1002 | "psr-7", 1003 | "request", 1004 | "response" 1005 | ], 1006 | "support": { 1007 | "source": "https://github.com/php-fig/http-message/tree/master" 1008 | }, 1009 | "time": "2016-08-06T14:39:51+00:00" 1010 | }, 1011 | { 1012 | "name": "psr/log", 1013 | "version": "1.1.4", 1014 | "source": { 1015 | "type": "git", 1016 | "url": "https://github.com/php-fig/log.git", 1017 | "reference": "d49695b909c3b7628b6289db5479a1c204601f11" 1018 | }, 1019 | "dist": { 1020 | "type": "zip", 1021 | "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", 1022 | "reference": "d49695b909c3b7628b6289db5479a1c204601f11", 1023 | "shasum": "" 1024 | }, 1025 | "require": { 1026 | "php": ">=5.3.0" 1027 | }, 1028 | "type": "library", 1029 | "extra": { 1030 | "branch-alias": { 1031 | "dev-master": "1.1.x-dev" 1032 | } 1033 | }, 1034 | "autoload": { 1035 | "psr-4": { 1036 | "Psr\\Log\\": "Psr/Log/" 1037 | } 1038 | }, 1039 | "notification-url": "https://packagist.org/downloads/", 1040 | "license": [ 1041 | "MIT" 1042 | ], 1043 | "authors": [ 1044 | { 1045 | "name": "PHP-FIG", 1046 | "homepage": "https://www.php-fig.org/" 1047 | } 1048 | ], 1049 | "description": "Common interface for logging libraries", 1050 | "homepage": "https://github.com/php-fig/log", 1051 | "keywords": [ 1052 | "log", 1053 | "psr", 1054 | "psr-3" 1055 | ], 1056 | "support": { 1057 | "source": "https://github.com/php-fig/log/tree/1.1.4" 1058 | }, 1059 | "time": "2021-05-03T11:20:27+00:00" 1060 | }, 1061 | { 1062 | "name": "ralouphie/getallheaders", 1063 | "version": "3.0.3", 1064 | "source": { 1065 | "type": "git", 1066 | "url": "https://github.com/ralouphie/getallheaders.git", 1067 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 1068 | }, 1069 | "dist": { 1070 | "type": "zip", 1071 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 1072 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 1073 | "shasum": "" 1074 | }, 1075 | "require": { 1076 | "php": ">=5.6" 1077 | }, 1078 | "require-dev": { 1079 | "php-coveralls/php-coveralls": "^2.1", 1080 | "phpunit/phpunit": "^5 || ^6.5" 1081 | }, 1082 | "type": "library", 1083 | "autoload": { 1084 | "files": [ 1085 | "src/getallheaders.php" 1086 | ] 1087 | }, 1088 | "notification-url": "https://packagist.org/downloads/", 1089 | "license": [ 1090 | "MIT" 1091 | ], 1092 | "authors": [ 1093 | { 1094 | "name": "Ralph Khattar", 1095 | "email": "ralph.khattar@gmail.com" 1096 | } 1097 | ], 1098 | "description": "A polyfill for getallheaders.", 1099 | "support": { 1100 | "issues": "https://github.com/ralouphie/getallheaders/issues", 1101 | "source": "https://github.com/ralouphie/getallheaders/tree/develop" 1102 | }, 1103 | "time": "2019-03-08T08:55:37+00:00" 1104 | } 1105 | ], 1106 | "packages-dev": [], 1107 | "aliases": [], 1108 | "minimum-stability": "beta", 1109 | "stability-flags": [], 1110 | "prefer-stable": false, 1111 | "prefer-lowest": false, 1112 | "platform": { 1113 | "php": ">=5.4" 1114 | }, 1115 | "platform-dev": [], 1116 | "plugin-api-version": "2.1.0" 1117 | } 1118 | -------------------------------------------------------------------------------- /credentials/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /index-raw.php: -------------------------------------------------------------------------------- 1 | client_id = $client_id; 34 | $this->client_secret = $client_secret; 35 | 36 | $this->token_dir = __DIR__ . '/credentials/'; 37 | $this->token_path = $this->token_dir . 'token.json'; 38 | } 39 | 40 | public function getTokenURL() { 41 | return "https://accounts.google.com/o/oauth2/auth?" . http_build_query([ 42 | 'response_type' => 'code', 43 | 'client_id' => $this->client_id, 44 | 'redirect_uri' => $this->redirect_uri, 45 | 'scope' => $this->scope, 46 | 'access_type' => 'offline', 47 | 'prompt' => 'consent' 48 | ]); 49 | } 50 | 51 | public function saveToken( $code ) { 52 | 53 | $data = [ 54 | 'code' => $code, 55 | 'client_id' => $this->client_id, 56 | 'client_secret' => $this->client_secret, 57 | 'redirect_uri' => $this->redirect_uri, 58 | 'grant_type' => 'authorization_code' 59 | ]; 60 | 61 | $ch = curl_init($this->token_url); 62 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 63 | curl_setopt($ch, CURLOPT_POST, true); 64 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); 65 | $response = curl_exec($ch); 66 | curl_close($ch); 67 | 68 | $token_data = json_decode($response, true); 69 | 70 | if (isset($token_data['access_token'])) { 71 | 72 | if ( ! file_exists( $this->token_dir ) ) { 73 | mkdir( $this->token_dir ); 74 | } 75 | 76 | $token_data['expires_in'] = time() + $token_data['expires_in']; 77 | 78 | file_put_contents( $this->token_path, json_encode($token_data)); 79 | header( 'Location: ' . $this->redirect_uri ); 80 | exit; 81 | } else { 82 | echo "Error getting access token!"; 83 | } 84 | } 85 | 86 | public function createMeeting() { 87 | 88 | $access_token_data = $this->getToken(); 89 | $access_token = $access_token_data['access_token']; 90 | $time = date('Y-m-d\TH:i:s-07:00', strtotime('tomorrow') + rand(0, 86399)); 91 | $endTime = date('Y-m-d\TH:i:s-07:00', strtotime($time) + 3600); 92 | 93 | $event = [ 94 | 'summary' => 'Demo Meeting - ' . microtime(true), 95 | 'location' => 'Online (Google Meet)', 96 | 'description' => 'Discussing project updates', 97 | 'start' => ['dateTime' => $time], 98 | 'end' => ['dateTime' => $endTime], 99 | 'conferenceData' => [ 100 | 'createRequest' => [ 101 | 'requestId' => uniqid(), 102 | 'conferenceSolutionKey' => ['type' => 'hangoutsMeet'] 103 | ] 104 | ] 105 | ]; 106 | 107 | $ch = curl_init('https://www.googleapis.com/calendar/v3/calendars/primary/events?conferenceDataVersion=1'); 108 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 109 | curl_setopt($ch, CURLOPT_POST, true); 110 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ 111 | 'Authorization: Bearer ' . $access_token, 112 | 'Content-Type: application/json' 113 | ]); 114 | 115 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($event)); 116 | $response = curl_exec($ch); 117 | curl_close($ch); 118 | 119 | header( 'Location: ' . $this->redirect_uri ); 120 | exit; 121 | } 122 | 123 | public function deleteMeeting( $event_id ) { 124 | 125 | $access_token_data = $this->getToken(); 126 | $access_token = $access_token_data['access_token']; 127 | 128 | $calendar_id = 'primary'; // Default calendar 129 | 130 | $api_url = "https://www.googleapis.com/calendar/v3/calendars/{$calendar_id}/events/{$event_id}"; 131 | 132 | $ch = curl_init(); 133 | curl_setopt($ch, CURLOPT_URL, $api_url); 134 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); 135 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 136 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ 137 | 'Authorization: Bearer ' . $access_token, 138 | 'Content-Type: application/json' 139 | ]); 140 | 141 | $response = curl_exec($ch); 142 | $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 143 | curl_close($ch); 144 | 145 | // Check response 146 | if ($http_code === 204) { 147 | header('Location: ' . $this->redirect_uri); 148 | exit; 149 | } else { 150 | echo "Failed to delete event. Response: " . $response; 151 | } 152 | } 153 | 154 | public function getMeetings() { 155 | 156 | $access_token_data = $this->getToken(); 157 | $access_token = $access_token_data['access_token']; 158 | 159 | $calendar_id = 'primary'; // Use 'primary' for the default calendar 160 | $api_url = "https://www.googleapis.com/calendar/v3/calendars/{$calendar_id}/events?" . http_build_query([ 161 | 'maxResults' => 50, 162 | 'timeMin' => date('c'), 163 | ]); 164 | 165 | $ch = curl_init(); 166 | curl_setopt($ch, CURLOPT_URL, $api_url); 167 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 168 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ 169 | 'Authorization: Bearer ' . $access_token, 170 | 'Content-Type: application/json' 171 | ]); 172 | 173 | $response = curl_exec($ch); 174 | curl_close($ch); 175 | 176 | $events = json_decode($response, true); 177 | $events = isset( $events['items'] ) ? $events['items'] : array(); 178 | $meetEvents = array(); 179 | 180 | 181 | foreach ( $events as $event ) { 182 | if ( 183 | isset($event['hangoutLink']) || 184 | ( 185 | isset($event['conferenceData']['conferenceId']) && 186 | isset($event['conferenceData']['conferenceSolution']['name']) && 187 | strpos(strtolower($event['conferenceData']['conferenceSolution']['name']), 'meet') !== false 188 | ) 189 | ) { 190 | $meetEvents[] = $event; 191 | } 192 | } 193 | 194 | 195 | return $meetEvents; 196 | } 197 | 198 | private function refreshToken( $old_token ) { 199 | 200 | // Request payload 201 | $data = [ 202 | 'client_id' => $this->client_id, 203 | 'client_secret' => $this->client_secret, 204 | 'refresh_token' => $old_token['refresh_token'], 205 | 'grant_type' => 'refresh_token' 206 | ]; 207 | 208 | $ch = curl_init(); 209 | curl_setopt($ch, CURLOPT_URL, $this->token_url); 210 | curl_setopt($ch, CURLOPT_POST, true); 211 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 212 | curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']); 213 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); 214 | 215 | $response = curl_exec($ch); 216 | curl_close($ch); 217 | 218 | $new_token = json_decode($response, true); 219 | 220 | if (isset($new_token['access_token'])) { 221 | 222 | // Update token file with new access_token 223 | $old_token['access_token'] = $new_token['access_token']; 224 | $old_token['expires_in'] = time() + $new_token['expires_in']; // Expiration time 225 | file_put_contents( $this->token_path, json_encode($old_token)); 226 | 227 | return $old_token; 228 | } else { 229 | echo "Failed to refresh token: " . $response; 230 | exit; 231 | } 232 | } 233 | 234 | private function getToken() { 235 | $token = json_decode(file_get_contents($this->token_path), true); 236 | if ( time() >= $token['expires_in'] ) { 237 | $token = $this->refreshToken( $token ); 238 | } 239 | return $token; 240 | } 241 | } 242 | 243 | // Follow the instructions here to get your credentials https://docs.themeum.com/tutor-lms/addons/google-meet-integration/#configuring-app-credentials 244 | $gm = new GM( 'YOUR_CLIENT_ID', 'YOUR_CLIENT_SECRET' ); 245 | 246 | if ( $gm->client_id === 'YOUR_CLIENT_ID' || $gm->client_secret === 'YOUR_CLIENT_SECRET' ) { 247 | echo '
Meeting title | 285 |Start | 286 |End | 287 |Link | 288 |Delete | 289 |
---|---|---|---|---|
295 | | 296 | | 297 | | 298 | | Delete | 299 |
No meeting found
'; 34 | } else { 35 | echo '' . $meeting['title'] . ' | 39 |' . $meeting['meeting_link'] . ' | 40 |' . $meeting['start'] . ' | 41 |Delete | 42 |Update with Random Data | 43 |