*/ namespace MillionsMissingFrance\FreescoutRestrictedCustomers\Http\Controllers; use App\Conversation; use App\Email; use Illuminate\Http\Request; use Validator; use App\Http\Controllers\CustomersController as BaseCustomersController; use MillionsMissingFrance\FreescoutRestrictedCustomers\Customer; class CustomersController extends BaseCustomersController { /** * Edit customer. */ public function update($id) { // TODO: Find a way to call parent::update while only overriding the Customer class, // instead of overriding the whole method here. $customer = Customer::findOrFail($id); $customer_emails = $customer->emails; if (count($customer_emails)) { foreach ($customer_emails as $row) { $emails[] = $row->email; } } else { $emails = ['']; } return view('customers/update', ['customer' => $customer, 'emails' => $emails]); } /** * Save customer. * * @param \Illuminate\Http\Request $request * * @return \Illuminate\Http\Response */ public function updateSave($id, Request $request) { // TODO: Find a way to call parent::updateSave while only overriding the Customer class, // instead of overriding the whole method here. function mb_ucfirst($string) { return mb_strtoupper(mb_substr($string, 0, 1)).mb_strtolower(mb_substr($string, 1)); } $customer = Customer::findOrFail($id); $flash_message = ''; // First name or email must be specified $validator = Validator::make($request->all(), [ 'first_name' => 'nullable|string|max:255|required_without:emails.0', 'last_name' => 'nullable|string|max:255', 'city' => 'nullable|string|max:255', 'state' => 'nullable|string|max:255', 'zip' => 'nullable|string|max:12', 'country' => 'nullable|string|max:2', //'emails' => 'array|required_without:first_name', //'emails.1' => 'nullable|email|required_without:first_name', 'emails.*' => 'nullable|email|distinct|required_without:first_name', 'photo_url' => 'nullable|image|mimes:jpeg,png,jpg,gif', ]); $validator->setAttributeNames([ 'photo_url' => __('Photo'), 'emails.*' => __('Email'), ]); // Photo $validator->after(function ($validator) use ($customer, $request) { if ($request->hasFile('photo_url')) { $path_url = $customer->savePhoto($request->file('photo_url')->getRealPath(), $request->file('photo_url')->getMimeType()); if ($path_url) { $customer->photo_url = $path_url; } else { $validator->errors()->add('photo_url', __('Error occurred processing the image. Make sure that PHP GD extension is enabled.')); } } }); if ($validator->fails()) { return redirect()->route('customers.update', ['id' => $id]) ->withErrors($validator) ->withInput(); } $new_emails = []; $new_emails_change_customer = []; $removed_emails = []; // Detect new emails added $customer_emails = $customer->emails()->pluck('email')->toArray(); foreach ($request->emails as $email) { if (!in_array($email, $customer_emails)) { $new_emails[] = $email; } } // If new email belongs to another customer, let user know about it in the flash message foreach ($new_emails as $new_email) { $email = Email::where('email', $new_email)->first(); if ($email && $email->customer) { // If customer whose email is removed does not have first name and other emails // we have to create first name for this customer if (!$email->customer->first_name && count($email->customer->emails) == 1) { if ($request->first_name) { $email->customer->first_name = $request->first_name; } elseif ($customer->first_name) { $email->customer->first_name = $customer->first_name; } else { $email->customer->first_name = mb_ucfirst($email->getNameFromEmail()); } $email->customer->save(); } $flash_message .= __('Email :tag_email_begin:email:tag_email_end has been moved from another customer: :a_begin:customer:a_end.', [ 'email' => $email->email, 'tag_email_begin' => '', 'tag_email_end' => '', 'customer' => $email->customer->getFullName(), 'a_begin' => '', 'a_end' => '', ]).' '; $new_emails_change_customer[] = $email; } } // Detect removed emails foreach ($customer_emails as $email) { if (!in_array($email, $request->emails)) { $removed_emails[] = $email; } } $request_data = $request->all(); if (isset($request_data['photo_url'])) { unset($request_data['photo_url']); } $customer->setData($request_data); // Websites // if (!empty($request->websites)) { // $customer->setWebsites($request->websites); // } $customer->save(); $customer->syncEmails($request->emails); // Update customer_id in all conversations added to the current customer. foreach ($new_emails_change_customer as $new_email) { if ($new_email->customer_id) { $conversations_to_change_customer = Conversation::where('customer_id', $new_email->customer_id)->get(); } else { // This does not work for phone conversations. $conversations_to_change_customer = Conversation::where('customer_email', $new_email->email)->get(); } foreach ($conversations_to_change_customer as $conversation) { // We have to pass user to create line item and let others know that customer has changed. // Conversation may be even in other mailbox where user does not have an access. $conversation->changeCustomer($new_email->email, $customer, auth()->user()); } } // Update customer in conversations for emails removed from current customer. foreach ($removed_emails as $removed_email) { $email = Email::where('email', $removed_email)->first(); if ($email) { $conversations = Conversation::where('customer_email', $email->email)->get(); foreach ($conversations as $conversation) { $conversation->changeCustomer($email->email, $email->customer, auth()->user()); } } } \Eventy::action('customer.updated', $customer); $flash_message = __('Customer saved successfully.').' '.$flash_message; \Session::flash('flash_success_unescaped', $flash_message); \Session::flash('customer.updated', 1); return redirect()->route('customers.update', ['id' => $id]); } /** * View customer conversations. * * @param intg $id */ public function conversations($id) { // TODO: Find a way to call parent::conversations while only overriding the Customer class, // instead of overriding the whole method here. $customer = Customer::findOrFail($id); $conversations = $customer->conversations() ->where('customer_id', $customer->id) ->whereIn('mailbox_id', auth()->user()->mailboxesIdsCanView()) ->orderBy('created_at', 'desc') ->paginate(Conversation::DEFAULT_LIST_SIZE); return view('customers/conversations', [ 'customer' => $customer, 'conversations' => $conversations, ]); } /** * Customers ajax search. */ public function ajaxSearch(Request $request) { // TODO: Find a way to call parent::ajaxSearch while only overriding the Customer class, // instead of overriding the whole method here. $response = [ 'results' => [], 'pagination' => ['more' => false], ]; $q = $request->q; $join_emails = false; if ($request->search_by == 'all' || $request->search_by == 'email' || $request->exclude_email) { $join_emails = true; } $select_list = ['customers.id', 'first_name', 'last_name']; if ($join_emails) { $select_list[] = 'emails.email'; } if ($request->show_fields == 'phone') { $select_list[] = 'phones'; } $customers_query = Customer::select($select_list); if ($join_emails) { if ($request->allow_non_emails) { $customers_query->leftJoin('emails', 'customers.id', '=', 'emails.customer_id'); } else { $customers_query->join('emails', 'customers.id', '=', 'emails.customer_id'); } } // Group the search terms query to avoid them from messing up the restriction by Mailbox. $customers_query->where(function($customers_query) use($request, $q) { if ($request->search_by == 'all' || $request->search_by == 'email') { $customers_query->where('emails.email', 'like', '%'.$q.'%'); if ($request->exclude_email) { $customers_query->where('emails.email', '<>', $request->exclude_email); } if ($request->search_by == 'all' || $request->search_by == 'name') { $customers_query->orWhere('first_name', 'like', '%'.$q.'%') ->orWhere('last_name', 'like', '%'.$q.'%'); } if ($request->search_by == 'phone') { $phone_numeric = \Helper::phoneToNumeric($q); if (!$phone_numeric) { $phone_numeric = $q; } $customers_query->where('customers.phones', 'like', '%'.$phone_numeric.'%'); } }); // Get the list of Mailboxes the current User has access to. $user = auth()->user(); $mailboxes = $user->mailboxesIdsCanView(); // Restrict the query to the Customers the current User is allowed to access. $customers_query->whereIn('customers.mailbox_id', $mailboxes); $customers = $customers_query->paginate(20); foreach ($customers as $customer) { $id = ''; $text = ''; if ($request->show_fields != 'all') { switch ($request->show_fields) { case 'email': $text = $customer->email; break; case 'name': $text = $customer->getFullName(); break; case 'phone': // Get phone which matches $phones = $customer->getPhones(); foreach ($phones as $phone) { $phone_numeric = \Helper::phoneToNumeric($q); if (strstr($phone['value'], $q) || strstr($phone['n'] ?? '', $phone_numeric)) { $text = $phone['value']; if ($customer->getFullName()) { $text .= ' — '.$customer->getFullName(); } $id = $phone['value']; break; } } break; default: $text = $customer->getNameAndEmail(); break; } } else { $text = $customer->getNameAndEmail(); } if (!$id) { if (!empty($request->use_id)) { $id = $customer->id; } else { $id = $customer->getMainEmail(); } } $response['results'][] = [ 'id' => $id, 'text' => $text, ]; } $response['pagination']['more'] = $customers->hasMorePages(); return \Response::json($response); } /** * Ajax controller. */ public function ajax(Request $request) { // TODO: Find a way to call parent::ajax while only overriding the Customer class, // instead of overriding the whole method here. $response = [ 'status' => 'error', 'msg' => '', // this is error message ]; $user = auth()->user(); switch ($request->action) { // Change conversation user case 'create': // First name or email must be specified $validator = Validator::make($request->all(), [ 'first_name' => 'required|string|max:255', 'last_name' => 'nullable|string|max:255', 'email' => 'required|email|unique:emails,email', ]); if ($validator->fails()) { foreach ($validator->errors()->getMessages()as $errors) { foreach ($errors as $field => $message) { $response['msg'] .= $message.' '; } } } if (!$response['msg']) { $customer = Customer::create($request->email, $request->all()); if ($customer) { $response['email'] = $request->email; $response['status'] = 'success'; } } break; // Conversations navigation case 'customers_pagination': $customers = app('MillionsMissingFrance\FreescoutRestrictedCustomers\Http\Controllers\ConversationsController')->searchCustomers($request, $user); $response['status'] = 'success'; $response['html'] = view('customers/partials/customers_table', [ 'customers' => $customers, ])->render(); break; default: $response['msg'] = 'Unknown action'; break; } if ($response['status'] == 'error' && empty($response['msg'])) { $response['msg'] = 'Unknown error occurred'; } return \Response::json($response); } }