ldc-crm/app/Http/Controllers/Bo/QuestionController.php
2023-10-06 16:37:30 +02:00

278 lines
9 KiB
PHP

<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\QuestionExport;
use App\Http\Requests\Bo\Questions\StoreQuestionRequest;
use App\Http\Requests\Bo\Questions\UpdateQuestionRequest;
use App\Models\Brand;
use App\Models\Question;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use League\Csv\Writer;
use Symfony\Component\HttpFoundation\StreamedResponse;
class QuestionController extends Controller
{
/**
* Display a listing of the resource.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function index(Request $request): \Illuminate\Contracts\View\View
{
/** @var \Illuminate\Database\Eloquent\Builder $query */
$query = Question::query();
if ($request->brand) {
$query = $query->where('brand_id', '=', $request->brand);
}
if ($request->search) {
$this->searchQuery(
$query,
$request->search,
null,
'question',
);
}
$this->sortQuery($query);
$searchFields = trans('Question');
$query->with(['brand', 'answers']);
/** @var \Illuminate\Pagination\AbstractPaginator */
$questionModels = $this->paginate($query);
return view('bo.pages.questions.index', compact('questionModels', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Question $question
* @return \Illuminate\Contracts\View\View
*/
public function create(Question $question): \Illuminate\Contracts\View\View
{
$brandModels = Brand::all();
return view('bo.pages.questions.create', [
'questionModel' => $question,
'brandModels' => $brandModels
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Questions\StoreQuestionRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreQuestionRequest $request): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request) {
$question = new Question();
$question->fill($request->validated());
if ($question->saveOrFail()) {
return redirect()
->route('bo.questions.edit', $question)
->with('success', trans(
':model a été créé.',
['model' => Str::singular(trans('models.classes.questions'))]
));
}
return redirect()
->back()
->with('error', trans(
':model n\'a pas été créé.',
['model' => Str::singular(trans('models.classes.questions'))]
));
});
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Question $question
* @return \Illuminate\Contracts\View\View
*/
public function edit(Question $question): \Illuminate\Contracts\View\View
{
$brandModels = Brand::all();
$question->load('brand');
return view('bo.pages.questions.edit', [
'questionModel' => $question,
'brandModels' => $brandModels
]);
}
/**
* Update a spacific resource in storage.
*
* @param \App\Http\Requests\Questions\UpdateQuestionRequest $request
* @param \App\Models\Question $question
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateQuestionRequest $request, Question $question): \Illuminate\Http\RedirectResponse
{
return DB::transaction(function () use ($request, $question) {
$question->fill($request->validated());
if ($question->saveOrFail()) {
return redirect()
->route('bo.questions.edit', $question)
->with('success', trans(
':model a été mis à jour.',
['model' => Str::singular(trans('models.classes.questions'))]
));
}
return redirect()
->back()
->with('error', trans(
':model n\'a pas été mis à jour.',
['model' => Str::singular(trans('models.classes.questions'))]
));
});
}
/**
* Show the specified resource.
*
* @param \App\Models\Question $question
* @return \Illuminate\Contracts\View\View
*/
public function show(Question $question): \Illuminate\Contracts\View\View
{
return view('bo.pages.questions.show', [
'questionModel' => $question
]);
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Question $question
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Question $question): \Illuminate\Http\RedirectResponse
{
if ($question->deleteOrFail()) {
return redirect()->route('bo.questions.index')
->with('success', trans(
':model a été supprimé.',
['model' => Str::singular(trans('models.classes.questions'))]
));
}
return redirect()->back()
->with('error', trans(
':model n\'a pas pu être supprimé.',
['model' => Str::singular(trans('models.classes.questions'))]
));
}
/**
* Shows the question export form
*
* @return \Illuminate\Contracts\View\View
*/
public function export(): \Illuminate\Contracts\View\View
{
$brands = Brand::all();
return view('bo.pages.questions.export', compact('brands'));
}
/**
* Exports questions as csv the requested export type
*
* @param \App\Http\Requests\QuestionExport $request
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
public function exportSubmit(QuestionExport $request): \Symfony\Component\HttpFoundation\StreamedResponse
{
$results = [];
/** @var \App\Models\Brand $brand */
$brand = Brand::query()->where('id', $request->brand)->firstOrFail();
$questions = $brand->questions->load('answers');
foreach ($questions as $question) {
$answersCounts = DB::query()
->selectRaw('count(*) as total, answer_id')
->from('customer_answer')
->whereIn('answer_id', $question->answers->pluck('id'))
->groupBy('answer_id')
->get()->keyBy('answer_id');
$results[$question->id] = [
'question' => $question->question,
'answers' => []
];
foreach ($question->answers as $answer) {
$results[$question->id]['answers'][] =
[
"$answer->answer ",
$answersCounts[$answer->id]->total ?? 0
];
}
}
$w = Writer::createFromString('');
$w->setDelimiter(';');
$w->setEnclosure('"');
$w->setOutputBOM(Writer::BOM_UTF8);
// * 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()->isoFormat('DD-MM-YYYY_HH-mm'),
Str::slug($brand->name)
)
);
foreach ($results as $result) {
$w->insertOne([
'question' => $result['question'],
]);
foreach ($result['answers'] as $answer) {
$w->insertOne($answer);
}
$w->insertOne([]);
}
// * Push empty line if nothing to export
if (empty($results)) {
$w->insertOne([
'Aucune question pour cette marque'
]);
}
/*
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;
}
}