Skip to content
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
UNRELEASED CHANGES:

* Add API calls to associate and remove tags to a contact
* Docker image: use cron to run schedule tasks
* Docker image: reduce size of image
* Docker image: create storage subdirectory in case they not exist
Expand Down
48 changes: 48 additions & 0 deletions app/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,16 @@ public function firstMetDate()
return $this->hasOne('App\SpecialDate', 'id', 'first_met_special_date_id');
}

/**
* Get the Notifications records associated with the account.
*
* @return HasMany
*/
public function notifications()
{
return $this->hasMany('App\Notification');
}

/**
* Sort the contacts according a given criteria.
* @param Builder $builder
Expand Down Expand Up @@ -1440,4 +1450,42 @@ public function getRelatedRealContact()
return self::find($relatedContact->is_the_child_of);
}
}

/**
* Sets a tag to the contact.
*
* @param string $tag
* @return Tag
*/
public function setTag(string $name)
{
$tag = $this->account->tags()->firstOrCreate([
'name' => $name,
]);

$tag->name_slug = str_slug($tag->name);
$tag->save();

$this->tags()->syncWithoutDetaching([$tag->id => ['account_id' => $this->account->id]]);

return $tag;
}

/**
* Unset all the tags associated with the contact.
* @return bool
*/
public function unsetTags()
{
$this->tags()->detach();
}

/**
* Unset one tag associated with the contact.
* @return bool
*/
public function unsetTag(Tag $tag)
{
$this->tags()->detach($tag->id);
}
}
106 changes: 106 additions & 0 deletions app/Http/Controllers/Api/ApiContactTagController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace App\Http\Controllers\Api;

use App\Tag;
use Validator;
use App\Contact;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use App\Http\Resources\Contact\Contact as ContactResource;

class ApiContactTagController extends ApiController
{
/**
* Associate one or more tags to the contact.
* @param Request $request
* @param int $contactId
*/
public function setTags(Request $request, $contactId)
{
try {
$contact = Contact::where('account_id', auth()->user()->account_id)
->where('id', $contactId)
->firstOrFail();
} catch (ModelNotFoundException $e) {
return $this->respondNotFound();
}

$validator = Validator::make($request->all(), [
'tags' => 'required|array',
]);

if ($validator->fails()) {
return $this->setErrorCode(32)
->respondWithError($validator->errors()->all());
}

$tags = $request->get('tags');
foreach ($tags as $tag) {
$contact->setTag($tag);
}

return new ContactResource($contact);
}

/**
* Remove all the tags associated with the contact.
* @param Request $request
* @param int $contactId
*/
public function unsetTags(Request $request, $contactId)
{
try {
$contact = Contact::where('account_id', auth()->user()->account_id)
->where('id', $contactId)
->firstOrFail();
} catch (ModelNotFoundException $e) {
return $this->respondNotFound();
}

$contact->unsetTags();

return new ContactResource($contact);
}

/**
* Remove one or more specific tags associated with the contact.
* @param Request $request
* @param int $contactId
*/
public function unsetTag(Request $request, $contactId)
{
try {
$contact = Contact::where('account_id', auth()->user()->account_id)
->where('id', $contactId)
->firstOrFail();
} catch (ModelNotFoundException $e) {
return $this->respondNotFound();
}

$validator = Validator::make($request->all(), [
'tags' => 'required|array',
]);

if ($validator->fails()) {
return $this->setErrorCode(32)
->respondWithError($validator->errors()->all());
}

$tags = $request->get('tags');
foreach ($tags as $tag) {
// does the tag exist?
try {
$tag = Tag::where('account_id', auth()->user()->account_id)
->where('id', $tag)
->firstOrFail();
} catch (ModelNotFoundException $e) {
return $this->respondNotFound();
}

$contact->unsetTag($tag);
}

return new ContactResource($contact);
}
}
13 changes: 2 additions & 11 deletions app/Http/Controllers/Contacts/TagsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,15 @@ public function update(TagsRequest $request, Contact $contact)

// if we receive an empty string, that means all tags have been removed.
if ($request->input('tags') == '') {
$contact->tags()->detach();
$contact->unsetTags();

return response()->json(['status' => 'no', 'tags' => '']);
}

$tagsIDs = [];
$tagsWithIdAndSlug = [];
foreach ($tags as $tag) {
$tag = auth()->user()->account->tags()->firstOrCreate([
'name' => $tag,
]);

$tag->name_slug = str_slug($tag->name);
$tag->save();

$tagsIDs[$tag->id] = ['account_id' => auth()->user()->account_id];
$tag = $contact->setTag($tag);

// this is passed back in json to JS
array_push($tagsWithIdAndSlug, [
Expand All @@ -50,8 +43,6 @@ public function update(TagsRequest $request, Contact $contact)
]);
}

$contact->tags()->sync($tagsIDs);

$response = [
'status' => 'yes',
'tags' => $tagsWithIdAndSlug,
Expand Down
3 changes: 3 additions & 0 deletions database/factories/ModelFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
'first_name' => 'John',
'last_name' => 'Doe',
'has_avatar' => false,
'gender_id' => function () {
return factory(App\Gender::class)->create()->id;
},
];
});

Expand Down
5 changes: 5 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
// Search for a contact
Route::post('/contacts/search', 'Api\\ApiContactController@search');

// Sets tags
Route::post('/contacts/{contact}/setTags', 'Api\\ApiContactTagController@setTags');
Route::get('/contacts/{contact}/unsetTags', 'Api\\ApiContactTagController@unsetTags');
Route::post('/contacts/{contact}/unsetTag', 'Api\\ApiContactTagController@unsetTag');

// Set a partner to the contact
Route::post('/contacts/{contact}/partners', 'Api\\ApiContactController@partners');
Route::post('/contacts/{contact}/partners/unset', 'Api\\ApiContactController@unsetPartners');
Expand Down
Loading