https://github.com/spinen/laravel-clickup
SPINEN's Laravel Package for ClickUp.
https://github.com/spinen/laravel-clickup
clickup clickup-api laravel-clickup
Last synced: 6 months ago
JSON representation
SPINEN's Laravel Package for ClickUp.
- Host: GitHub
- URL: https://github.com/spinen/laravel-clickup
- Owner: spinen
- Created: 2019-10-05T00:47:07.000Z (over 6 years ago)
- Default Branch: develop
- Last Pushed: 2024-04-08T12:07:32.000Z (about 2 years ago)
- Last Synced: 2025-10-10T00:53:33.038Z (9 months ago)
- Topics: clickup, clickup-api, laravel-clickup
- Language: PHP
- Homepage:
- Size: 141 KB
- Stars: 28
- Watchers: 7
- Forks: 15
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# SPINEN's Laravel ClickUp
[](https://packagist.org/packages/spinen/laravel-clickup)
[](https://packagist.org/packages/spinen/laravel-clickup)
[](https://packagist.org/packages/spinen/laravel-clickup)
[](https://packagist.org/packages/spinen/laravel-clickup)
PHP package to interface with [ClickUp](https://clickup.com). We strongly encourage you to review [ClickUp's API docs](https://clickup.com/api) to get a feel for what this package can do, as we are just wrapping their API.
We solely use [Laravel](https://www.laravel.com) for our applications, so this package is written with Laravel in mind. We have tried to make it work outside of Laravel. If there is a request from the community to split this package into 2 parts, then we will consider doing that work.
## Build Status
| Branch | Status | Coverage | Code Quality |
| ------ | :----: | :------: | :----------: |
| Develop | [](https://github.com/spinen/laravel-clickup/workflows/CI/badge.svg?branch=develop) | [](https://scrutinizer-ci.com/g/spinen/laravel-clickup/?branch=develop) | [](https://scrutinizer-ci.com/g/spinen/laravel-clickup/?branch=develop) |
| Master | [](https://github.com/spinen/laravel-clickup/workflows/CI/badge.svg?branch=master) | [](https://scrutinizer-ci.com/g/spinen/laravel-clickup/?branch=master) | [](https://scrutinizer-ci.com/g/spinen/laravel-clickup/?branch=master) |
## Table of Contents
* [Installation](#installation)
* [Laravel Setup](#laravel-setup)
* [Configuration](#configuration)
* [Optional Keys](#optional-keys)
* [Generic PHP Setup](#generic-php-setup)
* [Examples](#examples)
* [Authentication](#authentication)
* [OAuth](#oauth)
* [Personal Token](#personal-token)
* [Usage](#usage)
* [Supported Actions](#supported-actions)
* [Using the Client](#using-the-client)
* [Getting the Client object](#getting-the-client-object)
* [Models](#models)
* [Relationships](#relationships)
* [Advanced filtering using "where"](#advanced-filtering-using-where)
* [More Examples](#more-examples)
* [Known Issues](#known-issues)
## Installation
Install ClickUp PHP Package via Composer:
```bash
$ composer require spinen/laravel-clickup
```
The package uses the [auto registration feature](https://laravel.com/docs/master/packages#package-discovery) of Laravel.
## Laravel Setup
### Configuration
1. You will need to make your `User` object implement includes the `Spinen\ClickUp\Concerns\HasClickUp` trait which will allow it to access the Client as an attribute like this: `$user->clickup`
```php
CLICKUP_CLIENT_SECRET=
CLICKUP_OAUTH_URL=
CLICKUP_URL=
```
3. _[Optional]_ Publish config & migration
#### Config
A configuration file named ```clickup.php``` can be published to ```config/``` by running...
```bash
php artisan vendor:publish --tag=clickup-config
```
#### Migration
Migrations files can be published by running...
```bash
php artisan vendor:publish --tag=clickup-migrations
```
You'll need the migration to set the ClickUp API token on your `User` model.
## Generic PHP Setup
### Examples
To get a `Spinen\ClickUp\Api\Client` instance...
```bash
$ psysh
Psy Shell v0.9.9 (PHP 7.3.11 — cli) by Justin Hileman
>>> $configs = [
"oauth" => [
"id" => "", // if using OAuth
"secret" => "", // If using OAuth
"url" => "https://app.clickup.com/api",
],
"route" => [
"enabled" => true,
"middleware" => [
"web",
],
"sso" => "clickup/sso",
],
"url" => "https://api.clickup.com/api/v2",
];
>>> $guzzle = new GuzzleHttp\Client();
=> GuzzleHttp\Client {#2379}
>>> $clickup = new Spinen\ClickUp\Api\Client($configs, $guzzle) // Optionally, pass the token as 3rd parameter
=> Spinen\ClickUp\Api\Client {#2363}
>>> $clickup->setToken('') // Skip if passed in via constructor
=> Spinen\ClickUp\Api\Client {#2363}
```
The `$clickup` instance will work exactly like all of the examples below, so if you are not using Laravel, then you can use the package once you bootstrap the client.
## Authentication
ClickUp has 2 ways to authenticate when making API calls... 1) OAuth token or 2) Personal Token. Either method uses a token that is saved to the `clickup_token` property on the `User` model.
### OAuth
There is a middleware named `clickup` that you can apply to any route that verifies that the user has a `clickup_token`, and if the user does not, then it redirects the user to ClickUp's OAuth page with the `client_id` where the user selects the team(s) to link with your application. Upon selecting the team(s), the user is redirected to `/clickup/sso/?code=` where the system converts the `code` to a token & saves it to the user. Upon saving the `clickup_token`, the user is redirected to the initial page that was protected by the middleware.
> NOTE: You will need to have the `auth` middleware on the routes as the `User` is needed to see if there is a `clickup_token`.
If you do not want to use the `clickup` middleware to start the OAuth flow, then you can use the `oauthUri` on the `Client` to generate the link for the user...
```bash
$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.3.11 — cli) by Justin Hileman
>>> $clickup = app(Spinen\ClickUp\Api\Client::class)
=> Spinen\ClickUp\Api\Client {#3035}
>>> $clickup->oauthUri(route('clickup.sso.redirect_url', ))
=> "https://app.clickup.com/api?client_id=&redirect_uri=https%3A%2F%2F2Fclickup%2Fsso%2F"
>>>
```
> NOTE: At this time, there is not a way to remove a token that has been invalidated, so you will need to delete the `clickup_token` on the user to restart the flow.
### Personal Token
If you do not want to use the OAuth flow, then you can allow the user to provide you a personal token that you can save on the `User`.
```bash
$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.3.11 — cli) by Justin Hileman
>>> $user = App\User::find(1)
=> App\User {#3040
id: 1,
first_name: "Bob",
last_name: "Tester",
email: "bob.tester@example.com",
email_verified_at: null,
created_at: "2019-11-15 19:49:01",
updated_at: "2019-11-15 19:49:01",
logged_in_at: "2019-11-15 19:49:01",
deleted_at: null,
}
>>> $user->clickup_token = '';
=> ""
>>> $user->save()
=> true
```
## Usage
### Supported Actions
The primary class is `Spinen\ClickUp\Client`. It gets constructed with 3 parameters...
* `array $configs` - Configuration properties. See the `clickup.php` file in the `./config` directory for a documented list of options.
* `Guzzle $guzzle` - Instance of `GuzzleHttp\Client`
* `Token $token` - _[Optional]_ String of the user's token
Once you new up a `Client` instance, you have the following methods...
* `delete($path)` - Shortcut to the `request()` method with 'DELETE' as the last parameter
* `get($path)` - Shortcut to the `request()` method with 'GET' as the last parameter
* `oauthRequestTokenUsingCode($code)` - Request a token from the OAuth code
* `oauthUri($url)` - Build the URI to the OAuth page with the redirect_url set to `$url`
* `post($path, array $data)` - Shortcut to the `request()` method with 'POST' as the last parameter
* `put($path, array $data)` - Shortcut to the `request()` method with 'PUT' as the last parameter
* `request($path, $data = [], $method = 'GET')` - Make an [API call to ClickUp](https://clickup.com/api) to `$path` with the `$data` using the JWT for the logged in user.
* `setConfigs(array $configs)` - Allow overriding the `$configs` on the `Client` instance.
* `setToken($token)` - Set the token for the ClickUp API
* `uri($path = null, $url = null)` - Generate a full uri for the path to the ClickUp API.
### Using the Client
The Client is meant to emulate [Laravel's models with Eloquent](https://laravel.com/docs/master/eloquent#retrieving-models). When working with ClickUp resources, you can access properties and relationships [just like you would in Laravel](https://laravel.com/docs/master/eloquent-relationships#querying-relations).
#### Getting the Client object
By running the migration included in this package, your `User` class will have a `clickup_token` column on it. When you set the user's token, it is encrypted in your database with [Laravel's encryption methods](https://laravel.com/docs/master/encryption#using-the-encrypter). After setting the ClickUp API token, you can access the Client object through `$user->clickup`.
```php
$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.2.19 — cli) by Justin Hileman
>>> $user = User::find(1);
=> App\User {#3631
id: 1,
first_name: "Bob",
last_name: "Tester",
email: "bob.tester@example.com",
email_verified_at: null,
created_at: "2019-11-15 19:49:01",
updated_at: "2019-11-15 19:49:01",
logged_in_at: "2019-11-15 19:49:01",
deleted_at: null,
}
>>> // NOTE: Must have a clickup_token via one of the 2 ways in the Authentication section
>>> $user->clickup;
=> Spinen\ClickUp\Api\Client {#3635}
```
#### Models
The API responses are cast into models with the properties cast into the types as defined in the [ClickUp API documentation](https://clickup.com/api). You can review the models in the `src/` folder. There is a property named `casts` on each model that instructs the Client on how to cast the properties from the API response. If the `casts` property is empty, then the properties are not defined in the API docs, so an array is returned.
```php
>>> $team = $user->clickUp()->teams->first();
=> Spinen\ClickUp\Team {#3646
+exists: true,
+incrementing: false,
+parentModel: null,
+timestamps: false,
}
>>> $team->toArray(); // Calling toArray() is allowed just like in Laravel
=> [
"id" => <7 digit ClickUp ID>,
"name" => "SPINEN",
"color" => "#2980B9",
"avatar" => ,
"members" => [
[
// Keeps going
```
#### Relationships
Some of the responses have links to the related resources. If a property has a relationship, you can call it as a method and the additional calls are automatically made & returned. The value is stored in place of the original data, so once it is loaded it is cached.
```php
$folder = $team->spaces->first()->folders->first();
=> Spinen\ClickUp\Folder {#3632
+exists: true,
+incrementing: false,
+parentModel: Spinen\ClickUp\Space {#3658
+exists: true,
+incrementing: false,
+parentModel: Spinen\ClickUp\Team {#3645
+exists: true,
+incrementing: false,
+parentModel: null,
+timestamps: false,
},
+timestamps: false,
},
+timestamps: false,
}
>>> $folder->lists->count();
=> 5
>>> $folder->lists->first()->name;
=> "Test Folder"
```
You may also call these relationships as attributes, and the Client will return a `Collection` for you (just like Eloquent).
```php
>>> $folder->lists;
=> Spinen\ClickUp\Support\Collection {#3650
all: [
Spinen\ClickUp\TaskList {#3636
+exists: true,
+incrementing: false,
+parentModel: Spinen\ClickUp\Space {#3658
+exists: true,
+incrementing: false,
+parentModel: Spinen\ClickUp\Team {#3645
+exists: true,
+incrementing: false,
+parentModel: null,
+timestamps: false,
},
+timestamps: false,
},
+timestamps: false,
},
// Keeps going
```
#### Advanced filtering using "where"
You can do advanced filters by using `where` on the models
```php
>>> $team->tasks()->where('space_ids', ['space_id_1', 'space_id_2'])->where('assignees', ['assignee1', 'assignee2'])->get()->count();
=> 100
// If there are more than 100 results, they will be paginated. Pass in another parameter to get another page:
>>> $team->tasks()->where....->where('page', 2)->get();
```
> NOTE: The API has a page size of `100` records, so to get to the next page you use the `where` method... ```->where('page', 3)```
### More Examples
```php
>>> $team = $user->clickUp()->teams->first();
=> Spinen\ClickUp\Team {#3646
+exists: true,
+incrementing: false,
+parentModel: null,
+timestamps: false,
}
>>> $first_space = $team->spaces->first();
=> Spinen\ClickUp\Space {#3695
+exists: true,
+incrementing: false,
+parentModel: Spinen\ClickUp\Team {#3646
+exists: true,
+incrementing: false,
+parentModel: null,
+timestamps: false,
},
+timestamps: false,
}
>>> $folder = $first_space->folders->first()->toArray();
=> [
"id" => <7 digit ClickUp ID>,
"name" => "Test folder",
"orderindex" => 3.0,
"override_statuses" => true,
"hidden" => false,
"task_count" => 79,
"archived" => false,
"lists" => [
// Keeps going
```
## Known Issues
// TODO: Document known issues as we find them