Skip to content

Commit 36141e6

Browse files
authored
Merge pull request #4 from wazzac/task/readmemd
alpha/enhancements: Updated the readme.md details and applied a few c…
2 parents af804f3 + 6a485a9 commit 36141e6

File tree

2 files changed

+178
-32
lines changed

2 files changed

+178
-32
lines changed

README.md

Lines changed: 166 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,90 @@ The idea around this library is to make it very easy for a developer to define i
1414

1515
After each first time successful sync, the CRM Object primary key will be stored in a mapping table against the local table primary key. This allows for quicker loading times for future changes.
1616

17-
Update your Model with 4 properties that define the rules for 3rd-party CRM synchronization:
18-
- @var string|array|null `$syncModelCrmEnvironment`; *Required
19-
- @var array `$syncModelCrmPropertyMapping`; *Required
20-
- @var array `$syncModelCrmUniqueSearch`;
21-
- @var string `$syncModelCrmRelatedObject`;
22-
- @var array `$syncModelCrmDeleteRules`;
23-
- @var array `$syncModelCrmActiveRules`;
24-
- @var array `$syncModelCrmAssociateRules`;
17+
Update your Model with 7 properties that define the rules for 3rd-party CRM synchronization:
18+
19+
- @var string|array|null `$syncModelCrmEnvironment`;
20+
> `config('sync_modeltocrm.api.environment')` will be used if not provided.
21+
- @var array `$syncModelCrmPropertyMapping`; _\*Required_
22+
- @var array `$syncModelCrmUniqueSearch`; _\*Required_
23+
- @var string `$syncModelCrmRelatedObject`;
24+
> `config('sync_modeltocrm.api.providers.{provider}.object_table_mapping')` will be used if this is not provided.
25+
- @var array `$syncModelCrmDeleteRules`; _\*Required for delete actions_
26+
- @var array `$syncModelCrmActiveRules`; _\*Required for restore actions_
27+
- @var array `$syncModelCrmAssociateRules`; _\*Required when associations are true_
2528

2629
Looking at the below example:
27-
1. the `User` Model will syncronize to both the `Sandbox` and `Production` **HubSpot** environments _($syncModelCrmEnvironment)_.
30+
31+
1. The `User` Model will syncronize to both the `Sandbox` and `Production` **HubSpot** environments _($syncModelCrmEnvironment)_.
2832
2. It will only syncronize the `name` and `email` properties to the HubSpot corresponding `firstname` and `email` fields _($syncModelCrmPropertyMapping)_.
29-
3. When there is no internal mapping yet stored, the CRM record will be uniquely loaded using the `email` property _($syncModelCrmUniqueSearch)_.
33+
3. When there are no internal mapping yet stored, the CRM record will be uniquely loaded using the `email` property _($syncModelCrmUniqueSearch)_.
3034
4. In order for the script to know which remote CRM object relates to the User model, `contact` _($syncModelCrmRelatedObject)_ have to be defined as the remote item.
3135
5. The _($syncModelCrmDeleteRules)_ property is used to instruct the Crm what action to take when a local record is deleted/removed. For example, when _SoftDeletes_ are enabled locally, the crm will use the `soft_delete` rules to update the crm records or alternatively Archive the record in the crm.
3236
6. The reverse to the above, _($syncModelCrmActiveRules)_ will be used to define the action that will be taken when deleted records are activated again.
3337
7. Finally, the non-required _($syncModelCrmAssociateRules)_ property is used to define the relationship (associations) between objects. e.g. `user` to `entity`.
3438

3539
```PHP
40+
<?php
41+
42+
namespace App\Models;
43+
44+
// use Illuminate\Contracts\Auth\MustVerifyEmail;
45+
use Illuminate\Database\Eloquent\Factories\HasFactory;
46+
use Illuminate\Foundation\Auth\User as Authenticatable;
47+
use Illuminate\Notifications\Notifiable;
48+
use Laravel\Sanctum\HasApiTokens;
49+
use App\Models\Entity;
50+
use Illuminate\Database\Eloquent\SoftDeletes;
51+
use Wazza\SyncModelToCrm\Http\Controllers\CrmProviders\HubSpotController;
52+
use Wazza\SyncModelToCrm\Traits\crmTrait;
53+
3654
class User extends Authenticatable
3755
{
38-
// .
39-
// ..
40-
// ... original Model content above.
56+
use HasApiTokens, HasFactory, Notifiable, SoftDeletes;
57+
58+
// include this if you wish to use the `Mutators function` or
59+
// $this->syncToCrm() directly as appose to the observer method
60+
use crmTrait;
61+
62+
/**
63+
* The attributes that are mass assignable.
64+
*
65+
* @var array<int, string>
66+
*/
67+
protected $fillable = [
68+
'name',
69+
'email',
70+
'password',
71+
];
72+
73+
/**
74+
* The attributes that should be hidden for serialization.
75+
*
76+
* @var array<int, string>
77+
*/
78+
protected $hidden = [
79+
'password',
80+
'remember_token',
81+
];
82+
83+
/**
84+
* The attributes that should be cast.
85+
*
86+
* @var array<string, string>
87+
*/
88+
protected $casts = [
89+
'email_verified_at' => 'datetime',
90+
'password' => 'hashed',
91+
];
92+
93+
/**
94+
* Function that will be used to return the relationship data
95+
* @return type
96+
*/
97+
public function entity()
98+
{
99+
return $this->belongsTo(Entity::class)->withTrashed();
100+
}
41101

42102
// --------------------------------------------------------------
43103
// Sync Model to CRM
@@ -46,33 +106,37 @@ class User extends Authenticatable
46106
/**
47107
* The CRM provider environment/s to use (e.g. production, sandbox, etc.)
48108
* Use an array to sync to multiple environments.
49-
* `null` will take the default defined value from the config file.
109+
* `null` (or not defined) will take the default from the config file.
50110
*
51111
* @var string|array|null
52112
*/
53-
public $syncModelCrmEnvironment = ['sandbox', 'production'];
113+
public $syncModelCrmEnvironment = ['sandbox']; // ..or ['sandbox','production']
54114

55115
/**
56116
* Mapping array for local and CRM properties
57117
* This will be the primary property used to cycle through the crm providers
118+
* and properties to sync the model to the CRM.
119+
* Required - if not provided, the sync will process will be skipped (no Exceptions will be thrown)
58120
*
59121
* @var array
60122
*/
61123
public $syncModelCrmPropertyMapping = [
62124
'hubspot' => [
63125
'name' => 'firstname',
64126
'email' => 'email',
127+
// ... add all the properties that you would like to sync
65128
],
66129
];
67130

68131
/**
69132
* Unique filters for the CRM to locate the record if there is no internal mapping available.
133+
* Not required, but strongly encouraged to be configured as to avoid any duplicate record creation in the crm
70134
*
71135
* @var array
72136
*/
73137
public $syncModelCrmUniqueSearch = [
74138
'hubspot' => [
75-
'email' => 'email',
139+
'email' => 'email', // this will ensure that the search filter is unique
76140
],
77141
];
78142

@@ -107,6 +171,8 @@ class User extends Authenticatable
107171
/**
108172
* The Crm Active/Restore rules to follow.
109173
* These will be the rules to follow for any new entries that are not soft-deleted.
174+
*
175+
* @var array
110176
*/
111177
public $syncModelCrmActiveRules = [
112178
'hubspot' => [
@@ -127,28 +193,84 @@ class User extends Authenticatable
127193
'provider' => [
128194
'hubspot' => [
129195
[
130-
'association_category' => \Wazza\SyncModelToCrm\Http\Controllers\CrmProviders\HubSpotController::ASSOCIATION_CATEGORY__HUBSPOT_DEFINED,
131-
'association_type_id' => \Wazza\SyncModelToCrm\Http\Controllers\CrmProviders\HubSpotController::ASSOCIATION_TYPE_ID__CONTACT_TO_COMPANY_PRIMARY,
196+
'association_category' => HubSpotController::ASSOCIATION_CATEGORY__HUBSPOT_DEFINED,
197+
'association_type_id' => HubSpotController::ASSOCIATION_TYPE_ID__CONTACT_TO_COMPANY_PRIMARY,
132198
],
133199
[
134-
'association_category' => \Wazza\SyncModelToCrm\Http\Controllers\CrmProviders\HubSpotController::ASSOCIATION_CATEGORY__HUBSPOT_DEFINED,
135-
'association_type_id' => \Wazza\SyncModelToCrm\Http\Controllers\CrmProviders\HubSpotController::ASSOCIATION_TYPE_ID__CONTACT_TO_COMPANY,
200+
'association_category' => HubSpotController::ASSOCIATION_CATEGORY__HUBSPOT_DEFINED,
201+
'association_type_id' => HubSpotController::ASSOCIATION_TYPE_ID__CONTACT_TO_COMPANY,
136202
],
137203
],
138204
],
139205
],
140206
];
207+
208+
// --------------------------------------------------------------
209+
// Custom Methods to initiate a sync
210+
// --------------------------------------------------------------
211+
212+
/**
213+
* (1) Register the observer in the AppServiceProvider boot method
214+
*
215+
* public function boot(): void
216+
* {
217+
* // register the observer/s
218+
* // ...refer the the template examples in the sync-model-to-crm repo for a observer working copy
219+
* \App\Models\User::observe(\App\Observers\UserObserver::class);
220+
* }
221+
*/
222+
223+
224+
/**
225+
* (2) Mutators function (Laravel 5.4 or above)
226+
*
227+
* Laravel provides mutators which are methods that can be defined on a model to modify
228+
* attributes before they are saved. You can create a custom mutator named save that
229+
* first calls the original save method using parent::save() and then performs your
230+
* additional action.
231+
*
232+
* @param array $options
233+
* @return void
234+
*/
235+
public function save(array $options = [])
236+
{
237+
parent::save($options);
238+
239+
// lets call the syncModelToCrm method to sync the model to the CRM.
240+
// refer to the trait for all the available methods
241+
// $this->syncToCrmPatch(); -- disabled as we are currently using the observer method
242+
}
141243
}
142244
```
143245

144246
## Usage
145247

146-
The are primarily 2 methods that you can use to initiate a Model sync.
248+
The are a few methods that you can use to initiate a Model sync.
147249

148250
Executing `(new CrmController())->setModel($user)->execute();`:
251+
149252
1. Directly in a controller action.
150-
2. Via a Observer. e.g. inside a UserObserver to trigger after a save() event. (see below)
253+
2. Using the trait inside the model as a type of Mutators function.
254+
3. Via a Observer. e.g. inside a UserObserver to trigger after a save() event. (see below)
255+
151256
```PHP
257+
<?php
258+
259+
namespace App\Observers;
260+
261+
use App\Models\User;
262+
use Wazza\SyncModelToCrm\Http\Controllers\CrmController;
263+
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
264+
265+
/**
266+
* Register the observer in the AppServiceProvider boot method
267+
*
268+
* public function boot(): void
269+
* {
270+
* // register the observer/s
271+
* \App\Models\User::observe(\App\Observers\UserObserver::class);
272+
* }
273+
*/
152274
class UserObserver implements ShouldHandleEventsAfterCommit
153275
{
154276
/**
@@ -157,7 +279,10 @@ Executing `(new CrmController())->setModel($user)->execute();`:
157279
public function created(User $user): void
158280
{
159281
echo ('create...');
160-
(new CrmController())->setModel($user)->execute(CrmController::EXEC_ACTION_CREATE);
282+
(new CrmController())
283+
->setModel($user)
284+
->setAttemptCreate()
285+
->execute(true);
161286
echo ('created...');
162287
}
163288

@@ -169,7 +294,8 @@ Executing `(new CrmController())->setModel($user)->execute();`:
169294
echo ('update...');
170295
(new CrmController())
171296
->setModel($user)
172-
->execute(CrmController::EXEC_ACTION_UPDATE, true);
297+
->setAttemptUpdate()
298+
->execute(true);
173299
echo ('updated...');
174300
}
175301

@@ -180,7 +306,10 @@ Executing `(new CrmController())->setModel($user)->execute();`:
180306
public function deleted(User $user)
181307
{
182308
echo ('delete...');
183-
(new CrmController())->setModel($user)->execute(CrmController::EXEC_ACTION_DELETE);
309+
(new CrmController())
310+
->setModel($user)
311+
->setAttemptDelete()
312+
->execute();
184313
echo ('deleted...');
185314
}
186315

@@ -191,7 +320,10 @@ Executing `(new CrmController())->setModel($user)->execute();`:
191320
public function restored(User $user): void
192321
{
193322
echo ('restore...');
194-
(new CrmController())->setModel($user)->execute(CrmController::EXEC_ACTION_RESTORE);
323+
(new CrmController())
324+
->setModel($user)
325+
->setAttemptRestore()
326+
->execute();
195327
echo ('restored...');
196328
}
197329

@@ -210,10 +342,16 @@ Executing `(new CrmController())->setModel($user)->execute();`:
210342
public function saved(User $user): void
211343
{
212344
echo ('saving...');
345+
(new CrmController())
346+
->setModel($user)
347+
->setAttemptAll() // open for anything...
348+
->execute();
349+
echo ('saved...');
213350
}
214351
}
215352
```
216-
3. Inside an event job. This is a good method to separate the logic from the save event and put the sync in a job queue to be processed shortly after the record has been saved.
353+
354+
4. Inside an event job. This is a good method to separate the logic from the save event and put the sync in a job queue to be processed shortly after the record has been saved.
217355

218356
## Installation
219357

@@ -259,6 +397,7 @@ Executing `(new CrmController())->setModel($user)->execute();`:
259397
```
260398

261399
4. Below are some of the environment keys that can be added to your _.env_ configuration. If you need more information what each item does, refer to the `config/sync_modeltocrm.php` config file.
400+
262401
```
263402
SYNC_MODEL_TO_CRM_HASH_SALT=Ey4cw2BHvi0HmGYjyqYr
264403
SYNC_MODEL_TO_CRM_HASH_ALGO=sha256

src/Http/Controllers/CrmController.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -601,13 +601,18 @@ public function execute($associate = false, $actionEnvironment = null, $actionPr
601601

602602
// set the filter actual values from the model data
603603
$crmFilterData = [];
604-
foreach ($crmFilters as $localProperty => $crmProperty) {
605-
$crmFilterData[$crmProperty] = $this->model->{$localProperty} ?? null;
604+
if (!empty($crmFilters)) {
605+
foreach ($crmFilters as $localProperty => $crmProperty) {
606+
$crmFilterData[$crmProperty] = $this->model->{$localProperty} ?? null;
607+
}
606608
}
607609
$crmObject->logger->infoLow('Crm filter properties set as: ' . json_encode($crmFilterData));
608610

611+
// get the external object id
612+
$extObjectId = $keyLookup->ext_object_id ?? null;
613+
609614
// load the crm data (if exists)
610-
$crmObject->load($keyLookup->ext_object_id ?? null, $crmFilterData);
615+
$crmObject->load($extObjectId, $crmFilterData);
611616

612617
// define what action is requested (create, update, delete, restore)
613618
// -- (1) Patch: create a new record in the CRM -------------------
@@ -756,8 +761,10 @@ public function execute($associate = false, $actionEnvironment = null, $actionPr
756761

757762
// set the filter actual values from the model data
758763
$crmAssocFilterData = [];
759-
foreach ($crmAssocFilters as $localProperty => $crmProperty) {
760-
$crmAssocFilterData[$crmProperty] = $associatedModel->{$localProperty} ?? null;
764+
if (!empty($crmAssocFilters)) {
765+
foreach ($crmAssocFilters as $localProperty => $crmProperty) {
766+
$crmAssocFilterData[$crmProperty] = $associatedModel->{$localProperty} ?? null;
767+
}
761768
}
762769
$crmAssocObject->logger->infoLow('Crm filter properties set as: ' . json_encode($crmAssocFilterData));
763770

0 commit comments

Comments
 (0)