ldc-crm/app/Http/Controllers/QuestionController.php
Jérémy Munsch ebe8d8daa3
Fixes #3 Push empty line if no CSV question to export for a brand
(cherry picked from commit bf5477d15c56e33fe980dc67cbc10a0b18f58169)
2023-06-30 15:04:50 +02:00

277 lines
8.5 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Requests\QuestionExport;
use App\Http\Requests\Questions\StoreQuestionRequest;
use App\Http\Requests\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;
/**
* @codeCoverageIgnore
*/
class QuestionController extends Controller
{
/**
* Display a listing of the resource.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
/** @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');
/** @var \Illuminate\Pagination\AbstractPaginator */
$questionModels = $query->paginate(12);
return view('questions.index', compact('questionModels', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*
* @param \App\Models\Question $question
* @return \Illuminate\Http\Response
*/
public function create(Question $question)
{
$brandModels = Brand::get();
return view('questions.create', [
'questionModel' => $question,
'brandModels' => $brandModels
]);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Questions\StoreQuestionRequest $request
* @return \Illuminate\Http\Response
*/
public function store(StoreQuestionRequest $request)
{
return DB::transaction(function () use ($request) {
$question = new Question();
$question->fill($request->validated());
if ($question->saveOrFail()) {
return redirect()
->route('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\Http\Response
*/
public function edit(Question $question)
{
$brandModels = Brand::get();
return view('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\Response
*/
public function update(UpdateQuestionRequest $request, Question $question)
{
return DB::transaction(function () use ($request, $question) {
$question->fill($request->validated());
if ($question->saveOrFail()) {
return redirect()
->route('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\Http\Response
*/
public function show(Question $question)
{
return view('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('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\Http\Response
*/
public function export()
{
$brands = Brand::all();
return view('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)
{
$results = [];
$brand = Brand::findOrFail($request->brand);
$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()->format('d-m-Y_H-i'),
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;
}
}