freescout-restricted-customers/Entities/Customer.php

262 lines
6.4 KiB
PHP

<?php
/*
SPDX-License-Identifier: AGPL-3.0-only
SPDX-FileCopyrightText: © 2024 Millions Missing FRANCE <info@millionsmissing.fr>
*/
namespace Modules\MMFRestrictedCustomers;
use App\CustomerChannel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Watson\Rememberable\Rememberable;
use Modules\MMFRestrictedCustomers\Mailbox;
use App\Customer as BaseCustomer;
class Customer extends BaseCustomer {
/**
* Attributes fillable using fill() method.
*
* @var [type]
*/
protected $fillable = [
// Default list, imported from BaseCustomer.
'first_name',
'last_name',
'company',
'job_title',
'address',
'city',
'state',
'zip',
'country',
'photo_url',
'age',
'gender',
'notes',
'channel',
'channel_id',
'social_profiles',
// Addition specific to this package.
'mailbox_id',
];
/**
* Get the Mailbox that is allowed to access this Customer information.
*/
public function mailbox() {
return $this->belongsTo(Mailbox::class);
}
/**
* Create customer or get existing and fill empty fields.
*
* @param string $email
* @param array $data [description]
*
* @return [type] [description]
*/
public static function create($email, $data = []) {
$new = false;
$email = Email::sanitizeEmail($email);
if (!$email) {
return null;
}
$email_obj = Email::where('email', $email)->first();
if ($email_obj) {
$customer = $email_obj->customer;
// In case somehow the email has no customer.
if (!$customer) {
// Customer will be saved and connected to the email later.
$customer = new self();
}
// Update name if empty.
/*if (empty($customer->first_name) && !empty($data['first_name'])) {
$customer->first_name = $data['first_name'];
if (empty($customer->last_name) && !empty($data['last_name'])) {
$customer->last_name = $data['last_name'];
}
$customer->save();
}*/
} else {
$customer = new self();
$email_obj = new Email();
$email_obj->email = $email;
$new = true;
}
// Ensure that the Mailbox relationship is set, if provided.
if ( in_array('mailbox_id', $data) )
$customer->mailbox_id = $data['mailbox_id'];
// Set empty fields
if ($customer->setData($data, false) || !$customer->id) {
$customer->save();
}
if (empty($email_obj->id) || !$email_obj->customer_id || $email_obj->customer_id != $customer->id) {
// Email may have been set in setData().
$save_email = true;
if (!empty($data['emails']) && is_array($data['emails'])) {
foreach ($data['emails'] as $data_email) {
if (is_string($data_email) && $data_email == $email) {
$save_email = false;
break;
}
if (is_array($data_email) && !empty($data_email['value']) && $data_email['value'] == $email) {
$save_email = false;
break;
}
}
}
if ($save_email) {
$email_obj->customer()->associate($customer);
$email_obj->save();
}
}
// Todo: check phone uniqueness.
if ($new) {
\Eventy::action('customer.created', $customer);
}
return $customer;
}
/**
* Set empty fields.
*/
public function setData($data, $replace_data = true, $save = false) {
// Set the Mailbox this Customer should be linked to.
// TODO: Throw an error if the Mailbox is not set.
if ( isset($data['mailbox']) ) {
// TODO: Check that the current user is allowed to access this Mailbox.
$data['mailbox_id'] = $data['mailbox'];
unset($data['mailbox']);
}
return parent::setData($data, $replace_data, $save);
}
/**
* Only return a Customer instance if it is available to the current User.
*
* @param int $id
* @param array $columns
* @return mixed|static
*/
public static function find($id, $columns = ['*']) {
// Get the list of Mailboxes the current User has access to.
$user = auth()->user();
$mailboxes = $user->mailboxesIdsCanView();
$customer = self
::where('id', '=', $id)
->whereIn('mailbox_id', $mailboxes)
->first($columns);
}
/**
* Get the Mailboxes this Customer is linked to through Conversations.
*
* @return array
*/
public function mailboxesThroughConversations() {
return $this
->conversations
->pluck('mailbox')
->unique();
}
/**
* If this Customer is linked to a single Mailbox through Conversations, link it to it.
*/
public function linkToMailboxThroughConversations() {
$mailboxes = $this->mailboxesThroughConversations();
if ( $mailboxes->count() == 1 ) {
$this->mailbox_id = $mailboxes->first()->id;
$this->save();
}
}
/**
* Set customer emails.
*
* @param array $emails
*/
public function syncEmails($emails) {
if (is_array($emails)) {
$deleted_emails = [];
foreach ($this->emails as $email) {
foreach ($emails as $email_address) {
if (Email::sanitizeEmail($email->email) == Email::sanitizeEmail($email_address)) {
continue 2;
}
}
$deleted_emails[] = $email;
}
$mailbox = $this->mailbox;
foreach ($emails as $email_address) {
$email_address = Email::sanitizeEmail($email_address);
if (!$email_address) {
continue;
}
$email = Email
::whereInMailbox($mailbox)
->where('email', $email_address)
->first();
$new_emails = [];
if ($email) {
// Assign email to current customer
if ($email->customer_id != $this->id) {
$email->customer()->associate($this);
$email->save();
}
} else {
$new_emails[] = new Email(['email' => $email_address]);
}
if ($new_emails) {
$this->emails()->saveMany($new_emails);
}
}
foreach ($deleted_emails as $email) {
if (Conversation::where('customer_email', $email->email)->exists()) {
// Create customers for deleted emails
// if there is a conversation with 'customer_email'.
$customer = new self();
$customer->save();
$email->customer()->associate($customer);
$email->save();
} else {
// Simply delete an email.
$email->delete();
}
}
}
}
/**
* Add new email to customer.
*/
public function addEmail($email_address, $check_if_exists = false) {
// Check if email already exists and belongs to another customer.
if ($check_if_exists) {
$mailbox = $this->mailbox;
$email = Email
::whereInMailbox($mailbox)
->where('email', $email_address)
->first();
if ($email && !empty($email->customer_id)) {
return false;
}
}
$new_email = new Email(['email' => $email_address]);
$this->emails()->save($new_email);
}
}