middleware(function ($request, $next) { View::share('modelClass', Customer::class); return $next($request); }); } /** * View all customers * * @param Request $request * @return \Illuminate\Http\Response */ public function index(Request $request) { $modelTable = (new Customer())->getTable(); $modelClass = Customer::class; $brands = Brand::select('id', 'name')->get(); $columns = ['customer_infos.lastname', 'customer_infos.firstname']; // * Jointure pour pouvoir trier les colonnes. /** @var \Illuminate\Database\Eloquent\Builder */ $query = CustomerInfo::join('customer_logins', function (JoinClause $join) { $join->on('customer_logins.brand_id', '=', 'customer_infos.brand_id') ->on('customer_logins.customer_id', '=', 'customer_infos.customer_id'); }) ->join('customers', function (JoinClause $join) { $join->on('customers.id', '=', 'customer_infos.customer_id'); }) ->join('brands', function (JoinClause $join) { $join->on('brands.id', '=', 'customer_infos.brand_id'); }); if (request()->brand or Session::has("crud.$modelTable.brand")) { $brand = $request->brand ?? Session::get("crud.$modelTable.brand"); Session::put("crud.$modelTable.brand", $brand); $query = $query->where('customer_infos.brand_id', $brand); } // * Search on crud Label column. if ($request->search or Session::has("crud.$modelTable.search")) { $search = $request->search ?? Session::get("crud.$modelTable.search"); Session::put("crud.$modelTable.search", $search); $query->where(function ($q) use ($columns, $search) { foreach ($columns as $column) { $q = $q->orWhere($column, 'LIKE', "%$search%"); } $q = $q->orWhere('customers.email', 'LIKE', "%$search%"); $q = $q->orWhere('customer_logins.last_connection', 'LIKE', "%$search%"); }); } // * Sort columns. if ($request->sort_col) { Session::put("crud.$modelTable.sort_col", $request->sort_col); } if ($request->sort_way) { Session::put("crud.$modelTable.sort_way", $request->sort_way); } if ($request->rst) { Session::remove("crud.$modelTable.brand"); Session::remove("crud.$modelTable.search"); Session::remove("crud.$modelTable.sort_way"); Session::remove("crud.$modelTable.sort_col"); } if ( Session::has("crud.$modelTable.sort_col") and Session::has("crud.$modelTable.sort_way") and (Schema::hasColumn($modelTable, Session::get("crud.$modelTable.sort_col")) or in_array(Session::get("crud.$modelTable.sort_col"), [ 'brands.name', 'customers.email', 'customer_infos.firstname', 'customer_infos.lastname', 'customer_infos.opt_in', 'customer_logins.last_connection', 'customer_logins.status' ])) ) { $query = $query->orderBy( Session::get("crud.$modelTable.sort_col"), Session::get("crud.$modelTable.sort_way") ); } /** @var \Illuminate\Pagination\AbstractPaginator */ $customers = $query->paginate(config('crud.paginate', 50)); return view('customer.index', compact( 'modelClass', 'modelTable', 'customers', 'brands' )); } /** * Show a specific custmer * * @param Customer $customer * @param Brand $brand * @return \Illuminate\Http\Response */ public function show(Customer $customer, Brand $brand) { $customerInfos = CustomerInfo::where('customer_id', $customer->id) ->where('brand_id', $brand->id)->firstOrFail(); $customerLogin = CustomerLogin::where('customer_id', $customer->id) ->where('brand_id', $brand->id)->first(); return view('customer.show', compact( 'customerInfos', 'customerLogin' )); } /** * Delete a specific customer info * * @param Customer $customer * @param Brand $brand * @return \Illuminate\Http\RedirectResponse */ public function delete(Customer $customer, Brand $brand) { try { // TODO: Gestion avec mesBR. /** @var \App\Models\CustomerInfo */ $customerInfo = $customer->info($brand, Customer::FIRST_OR_FAIL); /** @var \App\Models\CustomerLogin */ $customerLogin = $customer->login($brand, Customer::FIRST_OR_FAIL); DB::transaction(function () use ( $brand, $customer, $customerLogin, $customerInfo ) { if ( $customerInfo->delete() === false || $customerLogin->delete() === false ) { throw new \ErrorException('Api failed to delete customer.'); }; $customer->optInHistory()->whereHas('brand', function ($q) use ($brand) { $q->where('id', $brand->id); })->delete(); $logins = $customer->logins()->count(); $infos = $customer->infos()->count(); $history = $customer->optInHistory()->count(); // If customer is not associated with any brand then delete. if (!$logins and !$infos and !$history) { if ($customer->delete() === false) { throw new \ErrorException('Api failed to update customer.'); } } }); } catch (\ErrorException $e) { return redirect()->route('customers.index') ->with('error', trans('Le compte n\'as pas pu être supprimé.')); } //end try return redirect()->route('customers.index')->with('warning', trans('Compte supprimé.')); } /** * Show export the customers form * * @return \Illuminate\Http\Response */ public function export() { $brands = Brand::all(); return view('customer.export', compact( 'brands' )); } /** * Exports customers following the requested export type * * @param CustomerExport $request * @return \Symfony\Component\HttpFoundation\StreamedResponse * @throws \Exception If the request export type in not handled. */ public function exportSubmit(CustomerExport $request) { $pagination = 2000; $header = '"lastname";"firstname";"email";"hashcode"'; $w = Writer::createFromString($header . PHP_EOL); $w->setDelimiter(';'); $w->setEnclosure('"'); $w->setOutputBOM(Writer::BOM_UTF8); $exportType = CustomerExportType::make(\intval($request->export_type)); // * We send the CSV using Symfony StreamedResponse. $response = new StreamedResponse(); $response->headers->set('Content-Encoding', 'none'); $response->headers->set('Content-Type', 'text/csv; charset=UTF-8'); $response->headers->set('Description', 'File Transfer'); $response->headers->set( 'Content-Disposition', sprintf( 'attachment; filename="Export pour newsletter %s %s.csv"', Carbon::now()->format('d-m-Y_H-i'), Str::slug($exportType) ) ); switch ($exportType) { case CustomerExportType::both(): $continue = true; // ! Continue case CustomerExportType::customer(): $page = 1; /** @var \Illuminate\Database\Eloquent\Builder $req */ $req = CustomerInfo::where('brand_id', $request->brand) ->where('opt_in', true); $total = $req->count(); $pages = \ceil($total / $pagination); do { /** @var \Illuminate\Pagination\LengthAwarePaginator $items */ $items = $req->with('customer', function ($q) { $q->select(['id', 'email']); })->paginate( $pagination, ['lastname', 'firstname', 'hashcode', 'customer_id'], 'page', $page ); $items->map(function (CustomerInfo $customerInfo) use ($w) { $w->insertOne([ 'lastname' => $customerInfo->lastname, 'firstname' => $customerInfo->firstname, 'email' => $customerInfo->customer->email, 'hashcode' => $customerInfo->hashcode ]); }); } while ($page++ <= $pages); if (!isset($continue)) { break; } // ! Continue case CustomerExportType::singleOptin(): SingleOptin::where('brand_id', $request->brand)->get() ->map(function (SingleOptin $singleOptin) use ($w) { $w->insertOne([ 'lastname' => '', 'firstname' => '', 'email' => $singleOptin->email, 'hashcode' => '' ]); }); break; default: throw new \Exception(sprintf('Unhandled CustomerExportType %s', $exportType->label)); } //end switch /* We create a callable to output the CSV in chunk with Symfony StreamResponse you can flush the body content if necessary see Symfony documentation for more information */ // * The flush value should depend on your CSV size. $flush_threshold = 1000; $response->setCallback(function () use ($w, $flush_threshold) { foreach ($w->chunk(1024) as $offset => $chunk) { echo $chunk; if ($offset % $flush_threshold === 0) { flush(); } } }); return $response; } }