Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add detach association #22

Merged
merged 2 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Interact with HubSpot's CRM with an enjoyable, Eloquent-like developer experienc
- Cursors provide a seamless way to loop through all records: `foreach(Contact::cursor() AS $contact) { ... }`

> **Note**
> Only the CRM API is currently implemented.
> Only the CRM API is currently implemented.

## Installation

Expand All @@ -24,7 +24,7 @@ composer require stechstudio/laravel-hubspot

### 2) Configure HubSpot

[Create a private HubSpot app](https://developers.hubspot.com/docs/api/private-apps#create-a-private-app) and give it appropriate scopes for what you want to do with this SDK.
[Create a private HubSpot app](https://developers.hubspot.com/docs/api/private-apps#create-a-private-app) and give it appropriate scopes for what you want to do with this SDK.

Copy the provided access token, and add to your Laravel `.env` file:

Expand Down Expand Up @@ -102,8 +102,8 @@ This package provides three different ways of fetching these results.

#### Paginating

Similar to a traditional database paginated result, you can paginate through a HubSpot collection of objects.
You will receive a `LengthAwarePaginator` just like with Eloquent, which means you can generate links in your UI just like you are used to.
Similar to a traditional database paginated result, you can paginate through a HubSpot collection of objects.
You will receive a `LengthAwarePaginator` just like with Eloquent, which means you can generate links in your UI just like you are used to.

```php
$contacts = Contact::paginate(20);
Expand All @@ -113,8 +113,8 @@ By default, this `paginate` method will look at the `page` query parameter. You

#### Cursor iteration

You can use the `cursor` method to iterate over the entire collection of objects.
This uses [lazy collections](https://laravel.com/docs/9.x/collections#lazy-collections) and [generators](https://www.php.net/manual/en/language.generators.overview.php)
You can use the `cursor` method to iterate over the entire collection of objects.
This uses [lazy collections](https://laravel.com/docs/9.x/collections#lazy-collections) and [generators](https://www.php.net/manual/en/language.generators.overview.php)
to seamlessly fetch chunks of records from the API as needed, hydrating objects when needed, and providing smooth iteration over a limitless number of objects.

```php
Expand All @@ -129,7 +129,7 @@ foreach(Contact::cursor() AS $contact) {

#### Manually fetching chunks

Of course, you can grab collections of records with your own manual pagination or chunking logic.
Of course, you can grab collections of records with your own manual pagination or chunking logic.
Use the `take` and `after` methods to specify what you want to grab, and then `get`.

```php
Expand All @@ -143,7 +143,7 @@ $contacts = Contact::get();
### Searching and filtering

When retrieving multiple objects, you will frequently want to filter, search, and order these results.
You can use a fluent interface to build up a query before retrieving the results.
You can use a fluent interface to build up a query before retrieving the results.

#### Adding filters

Expand Down Expand Up @@ -185,7 +185,7 @@ Contact::search('1234')->get();

#### Ordering

You can order the results with any property.
You can order the results with any property.

```php
Contact::orderBy('lastname')->get();
Expand All @@ -199,7 +199,7 @@ Contact::orderBy('days_to_close', 'desc')->get();

### Associations

HubSpot associations are handled similar to Eloquent relationships.
HubSpot associations are handled similar to Eloquent relationships.

#### Dynamic properties

Expand Down Expand Up @@ -230,7 +230,7 @@ Normally, there are three HubSpot API calls to achieve the above result:
2. Retrieve all the contact IDs that are associated to this company
3. Query for contacts that match the IDs

Now we can eliminate the second API call by eager loading the associated contact IDs.
Now we can eliminate the second API call by eager loading the associated contact IDs.
This library always eager-loads the IDs for associated companies, contacts, deals, and tickets. It does not eager-load
IDs for engagements like emails and notes, since those association will tend to be much longer lists.

Expand Down Expand Up @@ -258,7 +258,13 @@ This will create a new contact, associate it to the company, and return the new
You can also associate existing objects using `attach`. This method accepts and ID or an object instance.

```php
Company::find(555)->attach(Contact::find(123));
Company::find(555)->contacts()->attach(Contact::find(123));
```

You can also detach existing objects using `detach`. This method accepts and ID or an object instance.

```php
Company::find(555)->contacts()->detach(Contact::find(123));
```


Expand Down
13 changes: 12 additions & 1 deletion src/Api/Association.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ public function attach($targetId)
);
}

public function detach($targetId)
{
if ($targetId instanceof Model) {
$targetId = $targetId->id;
}

$this->sourceBuilder()->deleteAssociation(
$this->target, $targetId
);
}

public function sourceBuilder(): Builder
{
return $this->source->builder();
Expand All @@ -65,4 +76,4 @@ public function __call($method, $parameters)
{
return $this->forwardCallTo($this->builder(), $method, $parameters);
}
}
}
13 changes: 12 additions & 1 deletion src/Api/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,17 @@ public function associate(Model $target, $targetId)
)->json();
}

public function deleteAssociation(Model $target, $targetId)
{
return $this->client()->delete(
$this->object->endpoint('associate', [
'association' => $target->type(),
'associationId' => $targetId,
'associationType' => Str::singular($this->object->type()) . "_to_" . Str::singular($target->type())
])
)->json();
}

public function client(): Client
{
return $this->client;
Expand Down Expand Up @@ -408,4 +419,4 @@ public function __call($method, $parameters)
'Call to undefined method %s::%s()', static::class, $method
));
}
}
}
2 changes: 1 addition & 1 deletion src/Api/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function fill(array $properties): static

private function isAllowedProperty(string $key): bool
{
return $key === 'email' ||
return $key === 'email' ||
!(HubSpot::isType($key) || HubSpot::isType(Str::plural($key)));
}

Expand Down
Loading