Merge pull request #352 from shikorism/feature/319-csv-export
チェックインデータのエクスポート
This commit is contained in:
commit
9f047544b9
@ -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');
|
||||
|
57
app/Services/CheckinCsvExporter.php
Normal file
57
app/Services/CheckinCsvExporter.php
Normal 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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@
|
||||
href="{{ route('setting') }}"><span class="oi oi-person mr-1"></span> プロフィール</a>
|
||||
<a class="list-group-item list-group-item-action {{ Route::currentRouteName() === 'setting.privacy' ? 'active' : '' }}"
|
||||
href="{{ route('setting.privacy') }}"><span class="oi oi-shield mr-1"></span> プライバシー</a>
|
||||
<a class="list-group-item list-group-item-action {{ Route::currentRouteName() === 'setting.export' ? 'active' : '' }}"
|
||||
href="{{ route('setting.export') }}"><span class="oi oi-data-transfer-download mr-1"></span> データのエクスポート</a>
|
||||
<a class="list-group-item list-group-item-action {{ Route::currentRouteName() === 'setting.deactivate' ? 'active' : '' }}"
|
||||
href="{{ route('setting.deactivate') }}"><span class="oi oi-trash mr-1"></span> アカウントの削除</a>
|
||||
{{--<a class="list-group-item list-group-item-action {{ Route::currentRouteName() === 'setting.password' ? 'active' : '' }}"
|
||||
|
27
resources/views/setting/export.blade.php
Normal file
27
resources/views/setting/export.blade.php
Normal file
@ -0,0 +1,27 @@
|
||||
@extends('setting.base')
|
||||
|
||||
@section('title', 'データのエクスポート')
|
||||
|
||||
@section('tab-content')
|
||||
<h3>データのエクスポート</h3>
|
||||
<hr>
|
||||
<p>チェックインデータをCSVファイルとしてダウンロードすることができます。</p>
|
||||
<form class="mt-4" action="{{ route('setting.export.csv') }}" method="get">
|
||||
{{ csrf_field() }}
|
||||
<div class="mb-2"><strong>文字コード</strong></div>
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-radio custom-control-inline">
|
||||
<input id="charsetUTF8" class="custom-control-input" type="radio" name="charset" value="utf8" checked>
|
||||
<label for="charsetUTF8" class="custom-control-label">UTF-8</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio custom-control-inline ml-3">
|
||||
<input id="charsetSJIS" class="custom-control-input" type="radio" name="charset" value="sjis">
|
||||
<label for="charsetSJIS" class="custom-control-label">Shift_JIS</label>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-3">ダウンロード</button>
|
||||
</form>
|
||||
@endsection
|
||||
|
||||
@push('script')
|
||||
@endpush
|
@ -36,6 +36,8 @@ Route::middleware('auth')->group(function () {
|
||||
Route::post('/setting/profile', 'SettingController@updateProfile')->name('setting.profile.update');
|
||||
Route::get('/setting/privacy', 'SettingController@privacy')->name('setting.privacy');
|
||||
Route::post('/setting/privacy', 'SettingController@updatePrivacy')->name('setting.privacy.update');
|
||||
Route::get('/setting/export', 'SettingController@export')->name('setting.export');
|
||||
Route::get('/setting/export/csv', 'SettingController@exportToCsv')->name('setting.export.csv');
|
||||
Route::get('/setting/deactivate', 'SettingController@deactivate')->name('setting.deactivate');
|
||||
Route::post('/setting/deactivate', 'SettingController@destroyUser')->name('setting.deactivate.destroy');
|
||||
// Route::get('/setting/password', 'SettingController@password')->name('setting.password');
|
||||
|
Loading…
Reference in New Issue
Block a user