Export checkin to CSV

This commit is contained in:
shibafu
2020-05-20 01:50:34 +09:00
parent e872964144
commit cf9df74ed3
5 changed files with 115 additions and 0 deletions

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\DeactivatedUser;
use App\Services\CheckinCsvExporter;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
@@ -71,6 +72,36 @@ class SettingController extends Controller
return redirect()->route('setting.privacy')->with('status', 'プライバシー設定を更新しました。');
}
public function export()
{
return view('setting.export');
}
public function exportToCsv(Request $request)
{
$validated = $request->validate([
'charset' => ['required', Rule::in(['utf8', 'sjis'])]
]);
$charsets = [
'utf8' => 'UTF-8',
'sjis' => 'SJIS-win'
];
$filename = tempnam(sys_get_temp_dir(), 'tissue_export_tmp_');
try {
$exporter = new CheckinCsvExporter(Auth::user(), $filename, $charsets[$validated['charset']]);
$exporter->execute();
} catch (\Throwable $e) {
unlink($filename);
throw $e;
}
return response()
->download($filename, 'TissueCheckin_' . date('Y-m-d_H-i-s') . '.csv')
->deleteFileAfterSend(true);
}
public function deactivate()
{
return view('setting.deactivate');

View File

@@ -0,0 +1,57 @@
<?php
namespace App\Services;
use App\User;
use Illuminate\Support\Facades\DB;
use League\Csv\Writer;
class CheckinCsvExporter
{
/** @var User Target user */
private $user;
/** @var string Output filename */
private $filename;
/** @var string Output charset */
private $charset;
public function __construct(User $user, string $filename, string $charset)
{
$this->user = $user;
$this->filename = $filename;
$this->charset = $charset;
}
public function execute()
{
$csv = Writer::createFromPath($this->filename, 'wb');
$csv->setNewline("\r\n");
if ($this->charset === 'SJIS-win') {
$csv->addStreamFilter('convert.mbstring.encoding.UTF-8:SJIS-win');
}
$header = ['日時', 'ノート', 'オカズリンク'];
for ($i = 1; $i <= 32; $i++) {
$header[] = "タグ{$i}";
}
$csv->insertOne($header);
DB::transaction(function () use ($csv) {
// TODO: そんなに読み取り整合性を保つ努力はしていないのと、chunkの件数これでいいか分からない
$this->user->ejaculations()->with('tags')->orderBy('ejaculated_date')
->chunk(1000, function ($ejaculations) use ($csv) {
foreach ($ejaculations as $ejaculation) {
$record = [
$ejaculation->ejaculated_date->format('Y-m-d H:i'),
$ejaculation->note,
$ejaculation->link,
];
foreach ($ejaculation->tags as $tag) {
$record[] = $tag->name;
}
$csv->insertOne($record);
}
});
});
}
}