Skip to content

Commit

Permalink
Merge c63a1df into 274a4c0
Browse files Browse the repository at this point in the history
  • Loading branch information
akmolina28 committed Aug 6, 2020
2 parents 274a4c0 + c63a1df commit d1920d9
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 10 deletions.
31 changes: 31 additions & 0 deletions README.md
Expand Up @@ -128,6 +128,26 @@ Scroll down to the "Integrate calendar" section to see the id of the calendar. Y

![10](./docs/v2/10.png)

### Authentication with OAuth2

This package supports OAuth2 authentication. This allows you to authenticate with an actual Google account, and to create and manage events with your own Google account.

OAuth2 authentication requires a token file, in addition to the credentials file. The easiest way to generate both of these files is by using the [php quickstart tool](https://developers.google.com/calendar/quickstart/php). Following this guide will generate two files, `credentials.json` and `token.json`. They must be saved to your project as `oauth-credentials.json` and `oauth-token.json`, respectively. Check the config file in this package for exact details on where to save these files.

To use OAuth2, you must also set a new environment variable in your .env file:

```php
GOOGLE_CALENDAR_AUTH_PROFILE=oauth
```

If you are upgrading from an older version of this package, you will need to force a publish of the configuration:

```bash
php artisan vendor:publish --provider="Spatie\GoogleCalendar\GoogleCalendarServiceProvider" --force
```

Finally, for a more seamless experience in your application, instead of using the quickstart tool you can set up a consent screen in the [Google API console](https://console.developers.google.com/apis). This would allow non-technical users of your application to easily generate their own tokens. This is completely optional.

## Usage

### Getting events
Expand Down Expand Up @@ -244,6 +264,17 @@ $event = Event::find($eventId);
$event->delete();
```

## Setting a source

You can set source urls in your events, which are only visible to the creator of the event (see [docs](https://developers.google.com/calendar/v3/reference/events) for more on the source property). This function only works when authenticated via OAuth.

```php
$yourEvent->source = [
'title' => 'Test Source Title',
'url' => 'http://testsource.url',
];
```

### Limitations

The Google Calendar API provides many options. This package doesn't support all of them. For instance, recurring events cannot be managed properly with this package. If you stick to creating events with a name and a date you should be fine.
Expand Down
33 changes: 29 additions & 4 deletions config/google-calendar.php
Expand Up @@ -2,10 +2,35 @@

return [

/*
* Path to the json file containing the credentials.
*/
'service_account_credentials_json' => storage_path('app/google-calendar/service-account-credentials.json'),
'default_auth_profile' => env('GOOGLE_CALENDAR_AUTH_PROFILE', 'service_account'),

'auth_profiles' => [

/*
* Authenticate using a service account.
*/
'service_account' => [
/*
* Path to the json file containing the credentials.
*/
'credentials_json' => storage_path('app/google-calendar/service-account-credentials.json'),
],

/*
* Authenticate with actual google user account.
*/
'oauth' => [
/*
* Path to the json file containing the oauth2 credentials.
*/
'credentials_json' => storage_path('app/google-calendar/oauth-credentials.json'),

/*
* Path to the json file containing the oauth2 token.
*/
'token_json' => storage_path('app/google-calendar/oauth-token.json'),
],
],

/*
* The id of the Google Calendar that will be used by default.
Expand Down
23 changes: 23 additions & 0 deletions src/Event.php
Expand Up @@ -121,6 +121,13 @@ public function __get($name)
return $this->getSortDate();
}

if ($name === 'source') {
return [
'title' => $this->googleEvent->getSource()->title,
'url' => $this->googleEvent->getSource()->url,
];
}

$value = Arr::get($this->googleEvent, $name);

if (in_array($name, ['start.date', 'end.date']) && $value) {
Expand All @@ -144,6 +151,12 @@ public function __set($name, $value)
return;
}

if ($name == 'source') {
$this->setSourceProperty($value);

return;
}

Arr::set($this->googleEvent, $name, $value);
}

Expand Down Expand Up @@ -246,6 +259,16 @@ protected function setDateProperty(string $name, CarbonInterface $date)
}
}

protected function setSourceProperty(array $value)
{
$source = new \Google_Service_Calendar_EventSource([
'title' => $value['title'],
'url' => $value['url'],
]);

$this->googleEvent->setSource($source);
}

protected function getFieldName(string $name): string
{
return [
Expand Down
31 changes: 30 additions & 1 deletion src/GoogleCalendarFactory.php
Expand Up @@ -19,14 +19,43 @@ public static function createForCalendarId(string $calendarId): GoogleCalendar
}

public static function createAuthenticatedGoogleClient(array $config): Google_Client
{
$authProfile = $config['default_auth_profile'];

switch ($authProfile) {
case 'service_account':
return self::createServiceAccountClient($config['auth_profiles']['service_account']);
case 'oauth':
return self::createOAuthClient($config['auth_profiles']['oauth']);
}

throw new \InvalidArgumentException("Unsupported authentication profile [{$authProfile}].");
}

protected static function createServiceAccountClient(array $authProfile): Google_Client
{
$client = new Google_Client;

$client->setScopes([
Google_Service_Calendar::CALENDAR,
]);

$client->setAuthConfig($config['service_account_credentials_json']);
$client->setAuthConfig($authProfile['credentials_json']);

return $client;
}

protected static function createOAuthClient(array $authProfile): Google_Client
{
$client = new Google_Client;

$client->setScopes([
Google_Service_Calendar::CALENDAR,
]);

$client->setAuthConfig($authProfile['credentials_json']);

$client->setAccessToken(file_get_contents($authProfile['token_json']));

return $client;
}
Expand Down
42 changes: 37 additions & 5 deletions src/GoogleCalendarServiceProvider.php
Expand Up @@ -35,14 +35,46 @@ protected function guardAgainstInvalidConfiguration(array $config = null)
throw InvalidConfiguration::calendarIdNotSpecified();
}

$credentials = $config['service_account_credentials_json'];
$authProfile = $config['default_auth_profile'];

if (! is_array($credentials) && ! is_string($credentials)) {
throw InvalidConfiguration::credentialsTypeWrong($credentials);
switch ($authProfile) {
case 'service_account':
$this->validateServiceAccountConfigSettings($config);
break;
case 'oauth':
$this->validateOAuthConfigSettings($config);
break;
default:
throw new \InvalidArgumentException("Unsupported authentication profile [{$authProfile}].");
}
}

protected function validateServiceAccountConfigSettings(array $config = null)
{
$credentials = $config['auth_profiles']['service_account']['credentials_json'];

$this->validateConfigSetting($credentials);
}

protected function validateOAuthConfigSettings(array $config = null)
{
$credentials = $config['auth_profiles']['oauth']['credentials_json'];

$this->validateConfigSetting($credentials);

$token = $config['auth_profiles']['oauth']['token_json'];

$this->validateConfigSetting($token);
}

protected function validateConfigSetting(string $setting)
{
if (! is_array($setting) && ! is_string($setting)) {
throw InvalidConfiguration::credentialsTypeWrong($setting);
}

if (is_string($credentials) && ! file_exists($credentials)) {
throw InvalidConfiguration::credentialsJsonDoesNotExist($credentials);
if (is_string($setting) && ! file_exists($setting)) {
throw InvalidConfiguration::credentialsJsonDoesNotExist($setting);
}
}
}
12 changes: 12 additions & 0 deletions tests/Integration/EventTest.php
Expand Up @@ -100,6 +100,18 @@ public function it_can_set_a_location()
$this->assertEquals('Test Location', $this->event->googleEvent->getLocation());
}

/** @test */
public function it_can_set_a_source()
{
$this->event->source = [
'title' => 'Test Source Title',
'url' => 'http://testsource.url',
];

$this->assertEquals('Test Source Title', $this->event->googleEvent->getSource()->title);
$this->assertEquals('http://testsource.url', $this->event->googleEvent->getSource()->url);
}

/** @test */
public function it_can_determine_if_an_event_is_an_all_day_event()
{
Expand Down

0 comments on commit d1920d9

Please sign in to comment.